Asterisk - The Open Source Telephony Project  18.5.0
chan_mobile.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Bluetooth Mobile Device channel driver
22  *
23  * \author Dave Bowerman <[email protected]>
24  *
25  * \ingroup channel_drivers
26  */
27 
28 /*! \li \ref chan_mobile.c uses the configuration file \ref chan_mobile.conf
29  * \addtogroup configuration_file Configuration Files
30  */
31 
32 /*!
33  * \page chan_mobile.conf chan_mobile.conf
34  * \verbinclude chan_mobile.conf.sample
35  */
36 
37 /*** MODULEINFO
38  <depend>bluetooth</depend>
39  <defaultenabled>no</defaultenabled>
40  <support_level>extended</support_level>
41  ***/
42 
43 #include "asterisk.h"
44 
45 #include <pthread.h>
46 #include <signal.h>
47 
48 #include <bluetooth/bluetooth.h>
49 #include <bluetooth/hci.h>
50 #include <bluetooth/hci_lib.h>
51 #include <bluetooth/sdp.h>
52 #include <bluetooth/sdp_lib.h>
53 #include <bluetooth/rfcomm.h>
54 #include <bluetooth/sco.h>
55 #include <bluetooth/l2cap.h>
56 
57 #include "asterisk/compat.h"
58 #include "asterisk/lock.h"
59 #include "asterisk/callerid.h"
60 #include "asterisk/channel.h"
61 #include "asterisk/config.h"
62 #include "asterisk/logger.h"
63 #include "asterisk/module.h"
64 #include "asterisk/pbx.h"
65 #include "asterisk/options.h"
66 #include "asterisk/utils.h"
67 #include "asterisk/linkedlists.h"
68 #include "asterisk/cli.h"
69 #include "asterisk/devicestate.h"
70 #include "asterisk/causes.h"
71 #include "asterisk/dsp.h"
72 #include "asterisk/app.h"
73 #include "asterisk/manager.h"
74 #include "asterisk/io.h"
75 #include "asterisk/smoother.h"
76 #include "asterisk/format_cache.h"
77 
78 #define MBL_CONFIG "chan_mobile.conf"
79 #define MBL_CONFIG_OLD "mobile.conf"
80 
81 #define DEVICE_FRAME_SIZE 48
82 #define DEVICE_FRAME_FORMAT ast_format_slin
83 #define CHANNEL_FRAME_SIZE 320
84 
85 static int discovery_interval = 60; /* The device discovery interval, default 60 seconds. */
86 static pthread_t discovery_thread = AST_PTHREADT_NULL; /* The discovery thread */
87 static sdp_session_t *sdp_session;
88 
90 static int unloading_flag = 0;
91 static inline int check_unloading(void);
92 static inline void set_unloading(void);
93 
94 enum mbl_type {
97 };
98 
99 struct adapter_pvt {
100  int dev_id; /* device id */
101  int hci_socket; /* device descriptor */
102  char id[31]; /* the 'name' from mobile.conf */
103  bdaddr_t addr; /* adddress of adapter */
104  unsigned int inuse:1; /* are we in use ? */
105  unsigned int alignment_detection:1; /* do alignment detection on this adpater? */
106  struct io_context *io; /*!< io context for audio connections */
107  struct io_context *accept_io; /*!< io context for sco listener */
108  int *sco_id; /*!< the io context id of the sco listener socket */
109  int sco_socket; /*!< sco listener socket */
110  pthread_t sco_listener_thread; /*!< sco listener thread */
112 };
113 
115 
116 struct msg_queue_entry;
117 struct hfp_pvt;
118 struct mbl_pvt {
119  struct ast_channel *owner; /* Channel we belong to, possibly NULL */
120  struct ast_frame fr; /* "null" frame */
121  ast_mutex_t lock; /*!< pvt lock */
122  /*! queue for messages we are expecting */
124  enum mbl_type type; /* Phone or Headset */
125  char id[31]; /* The id from mobile.conf */
126  int group; /* group number for group dialling */
127  bdaddr_t addr; /* address of device */
128  struct adapter_pvt *adapter; /* the adapter we use */
129  char context[AST_MAX_CONTEXT]; /* the context for incoming calls */
130  struct hfp_pvt *hfp; /*!< hfp pvt */
131  int rfcomm_port; /* rfcomm port number */
132  int rfcomm_socket; /* rfcomm socket descriptor */
133  char rfcomm_buf[256];
135  struct ast_smoother *bt_out_smoother; /* our bt_out_smoother, for making 48 byte frames */
136  struct ast_smoother *bt_in_smoother; /* our smoother, for making "normal" CHANNEL_FRAME_SIZEed byte frames */
137  int sco_socket; /* sco socket descriptor */
138  pthread_t monitor_thread; /* monitor thread handle */
139  int timeout; /*!< used to set the timeout for rfcomm data (may be used in the future) */
140  unsigned int no_callsetup:1;
141  unsigned int has_sms:1;
142  unsigned int do_alignment_detection:1;
144  unsigned int blackberry:1;
145  short alignment_samples[4];
148  struct ast_dsp *dsp;
151 
152  /* flags */
153  unsigned int outgoing:1; /*!< outgoing call */
154  unsigned int incoming:1; /*!< incoming call */
155  unsigned int outgoing_sms:1; /*!< outgoing sms */
156  unsigned int incoming_sms:1; /*!< outgoing sms */
157  unsigned int needcallerid:1; /*!< we need callerid */
158  unsigned int needchup:1; /*!< we need to send a chup */
159  unsigned int needring:1; /*!< we need to send a RING */
160  unsigned int answered:1; /*!< we sent/received an answer */
161  unsigned int connected:1; /*!< do we have an rfcomm connection to a device */
162 
164 };
165 
166 /*! Structure used by hfp_parse_clip to return two items */
167 struct cidinfo {
168  char *cnum;
169  char *cnam;
170 };
171 
173 
174 static int handle_response_ok(struct mbl_pvt *pvt, char *buf);
175 static int handle_response_error(struct mbl_pvt *pvt, char *buf);
176 static int handle_response_ciev(struct mbl_pvt *pvt, char *buf);
177 static int handle_response_clip(struct mbl_pvt *pvt, char *buf);
178 static int handle_response_ring(struct mbl_pvt *pvt, char *buf);
179 static int handle_response_cmti(struct mbl_pvt *pvt, char *buf);
180 static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf);
181 static int handle_response_cusd(struct mbl_pvt *pvt, char *buf);
182 static int handle_response_busy(struct mbl_pvt *pvt);
183 static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf);
184 static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf);
185 static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf);
186 
187 /* CLI stuff */
188 static char *handle_cli_mobile_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
189 static char *handle_cli_mobile_search(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
190 static char *handle_cli_mobile_rfcomm(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
191 static char *handle_cli_mobile_cusd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
192 
193 static struct ast_cli_entry mbl_cli[] = {
194  AST_CLI_DEFINE(handle_cli_mobile_show_devices, "Show Bluetooth Cell / Mobile devices"),
195  AST_CLI_DEFINE(handle_cli_mobile_search, "Search for Bluetooth Cell / Mobile devices"),
196  AST_CLI_DEFINE(handle_cli_mobile_rfcomm, "Send commands to the rfcomm port for debugging"),
197  AST_CLI_DEFINE(handle_cli_mobile_cusd, "Send CUSD commands to the mobile"),
198 };
199 
200 /* App stuff */
201 static char *app_mblstatus = "MobileStatus";
202 static char *mblstatus_synopsis = "MobileStatus(Device,Variable)";
203 static char *mblstatus_desc =
204 "MobileStatus(Device,Variable)\n"
205 " Device - Id of mobile device from mobile.conf\n"
206 " Variable - Variable to store status in will be 1-3.\n"
207 " In order, Disconnected, Connected & Free, Connected & Busy.\n";
208 
209 static char *app_mblsendsms = "MobileSendSMS";
210 static char *mblsendsms_synopsis = "MobileSendSMS(Device,Dest,Message)";
211 static char *mblsendsms_desc =
212 "MobileSendSms(Device,Dest,Message)\n"
213 " Device - Id of device from mobile.conf\n"
214 " Dest - destination\n"
215 " Message - text of the message\n";
216 
217 static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo,
218  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor);
219 static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap,
220  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
221 static int mbl_call(struct ast_channel *ast, const char *dest, int timeout);
222 static int mbl_hangup(struct ast_channel *ast);
223 static int mbl_answer(struct ast_channel *ast);
224 static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
225 static struct ast_frame *mbl_read(struct ast_channel *ast);
226 static int mbl_write(struct ast_channel *ast, struct ast_frame *frame);
227 static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
228 static int mbl_devicestate(const char *data);
229 
230 static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen);
231 
232 static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control);
233 static int mbl_queue_hangup(struct mbl_pvt *pvt);
234 static int mbl_ast_hangup(struct mbl_pvt *pvt);
235 static int mbl_has_service(struct mbl_pvt *pvt);
236 
237 static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel);
238 static int rfcomm_write(int rsock, char *buf);
239 static int rfcomm_write_full(int rsock, char *buf, size_t count);
240 static int rfcomm_wait(int rsock, int *ms);
241 static ssize_t rfcomm_read(int rsock, char *buf, size_t count);
242 
243 static int sco_connect(bdaddr_t src, bdaddr_t dst);
244 static int sco_write(int s, char *buf, int len);
245 static int sco_accept(int *id, int fd, short events, void *data);
246 static int sco_bind(struct adapter_pvt *adapter);
247 
248 static void *do_sco_listen(void *data);
249 static int sdp_search(char *addr, int profile);
250 
251 static int headset_send_ring(const void *data);
252 
253 /*
254  * bluetooth handsfree profile helpers
255  */
256 
257 #define HFP_HF_ECNR (1 << 0)
258 #define HFP_HF_CW (1 << 1)
259 #define HFP_HF_CID (1 << 2)
260 #define HFP_HF_VOICE (1 << 3)
261 #define HFP_HF_VOLUME (1 << 4)
262 #define HFP_HF_STATUS (1 << 5)
263 #define HFP_HF_CONTROL (1 << 6)
264 
265 #define HFP_AG_CW (1 << 0)
266 #define HFP_AG_ECNR (1 << 1)
267 #define HFP_AG_VOICE (1 << 2)
268 #define HFP_AG_RING (1 << 3)
269 #define HFP_AG_TAG (1 << 4)
270 #define HFP_AG_REJECT (1 << 5)
271 #define HFP_AG_STATUS (1 << 6)
272 #define HFP_AG_CONTROL (1 << 7)
273 #define HFP_AG_ERRORS (1 << 8)
274 
275 #define HFP_CIND_UNKNOWN -1
276 #define HFP_CIND_NONE 0
277 #define HFP_CIND_SERVICE 1
278 #define HFP_CIND_CALL 2
279 #define HFP_CIND_CALLSETUP 3
280 #define HFP_CIND_CALLHELD 4
281 #define HFP_CIND_SIGNAL 5
282 #define HFP_CIND_ROAM 6
283 #define HFP_CIND_BATTCHG 7
284 
285 /* call indicator values */
286 #define HFP_CIND_CALL_NONE 0
287 #define HFP_CIND_CALL_ACTIVE 1
288 
289 /* callsetup indicator values */
290 #define HFP_CIND_CALLSETUP_NONE 0
291 #define HFP_CIND_CALLSETUP_INCOMING 1
292 #define HFP_CIND_CALLSETUP_OUTGOING 2
293 #define HFP_CIND_CALLSETUP_ALERTING 3
294 
295 /* service indicator values */
296 #define HFP_CIND_SERVICE_NONE 0
297 #define HFP_CIND_SERVICE_AVAILABLE 1
298 
299 /*!
300  * \brief This struct holds HFP features that we support.
301  */
302 struct hfp_hf {
303  int ecnr:1; /*!< echo-cancel/noise reduction */
304  int cw:1; /*!< call waiting and three way calling */
305  int cid:1; /*!< cli presentation (callier id) */
306  int voice:1; /*!< voice recognition activation */
307  int volume:1; /*!< remote volume control */
308  int status:1; /*!< enhanced call status */
309  int control:1; /*!< enhanced call control*/
310 };
311 
312 /*!
313  * \brief This struct holds HFP features the AG supports.
314  */
315 struct hfp_ag {
316  int cw:1; /*!< three way calling */
317  int ecnr:1; /*!< echo-cancel/noise reduction */
318  int voice:1; /*!< voice recognition */
319  int ring:1; /*!< in band ring tone capability */
320  int tag:1; /*!< attach a number to a voice tag */
321  int reject:1; /*!< ability to reject a call */
322  int status:1; /*!< enhanced call status */
323  int control:1; /*!< enhanced call control*/
324  int errors:1; /*!< extended error result codes*/
325 };
326 
327 /*!
328  * \brief This struct holds mappings for indications.
329  */
330 struct hfp_cind {
331  int service; /*!< whether we have service or not */
332  int call; /*!< call state */
333  int callsetup; /*!< bluetooth call setup indications */
334  int callheld; /*!< bluetooth call hold indications */
335  int signal; /*!< signal strength */
336  int roam; /*!< roaming indicator */
337  int battchg; /*!< battery charge indicator */
338 };
339 
340 
341 /*!
342  * \brief This struct holds state information about the current hfp connection.
343  */
344 struct hfp_pvt {
345  struct mbl_pvt *owner; /*!< the mbl_pvt struct that owns this struct */
346  int initialized:1; /*!< whether a service level connection exists or not */
347  int nocallsetup:1; /*!< whether we detected a callsetup indicator */
348  struct hfp_ag brsf; /*!< the supported feature set of the AG */
349  int cind_index[16]; /*!< the cind/ciev index to name mapping for this AG */
350  int cind_state[16]; /*!< the cind/ciev state for this AG */
351  struct hfp_cind cind_map; /*!< the cind name to index mapping for this AG */
352  int rsock; /*!< our rfcomm socket */
353  int rport; /*!< our rfcomm port */
354  int sent_alerting; /*!< have we sent alerting? */
355 };
356 
357 
358 /* Our supported features.
359  * we only support caller id
360  */
361 static struct hfp_hf hfp_our_brsf = {
362  .ecnr = 0,
363  .cw = 0,
364  .cid = 1,
365  .voice = 0,
366  .volume = 0,
367  .status = 0,
368  .control = 0,
369 };
370 
371 
372 static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value);
373 static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf);
374 static int parse_next_token(char string[], const int start, const char delim);
375 static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf);
376 static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text);
377 static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf);
378 static int hfp_parse_cind(struct hfp_pvt *hfp, char *buf);
379 static int hfp_parse_cind_test(struct hfp_pvt *hfp, char *buf);
380 static char *hfp_parse_cusd(struct hfp_pvt *hfp, char *buf);
381 
382 static int hfp_brsf2int(struct hfp_hf *hf);
383 static struct hfp_ag *hfp_int2brsf(int brsf, struct hfp_ag *ag);
384 
385 static int hfp_send_brsf(struct hfp_pvt *hfp, struct hfp_hf *brsf);
386 static int hfp_send_cind(struct hfp_pvt *hfp);
387 static int hfp_send_cind_test(struct hfp_pvt *hfp);
388 static int hfp_send_cmer(struct hfp_pvt *hfp, int status);
389 static int hfp_send_clip(struct hfp_pvt *hfp, int status);
390 static int hfp_send_vgs(struct hfp_pvt *hfp, int value);
391 
392 #if 0
393 static int hfp_send_vgm(struct hfp_pvt *hfp, int value);
394 #endif
395 static int hfp_send_dtmf(struct hfp_pvt *hfp, char digit);
396 static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode);
397 static int hfp_send_cnmi(struct hfp_pvt *hfp);
398 static int hfp_send_cmgr(struct hfp_pvt *hfp, int index);
399 static int hfp_send_cmgs(struct hfp_pvt *hfp, const char *number);
400 static int hfp_send_sms_text(struct hfp_pvt *hfp, const char *message);
401 static int hfp_send_chup(struct hfp_pvt *hfp);
402 static int hfp_send_atd(struct hfp_pvt *hfp, const char *number);
403 static int hfp_send_ata(struct hfp_pvt *hfp);
404 static int hfp_send_cusd(struct hfp_pvt *hfp, const char *code);
405 
406 /*
407  * bluetooth headset profile helpers
408  */
409 static int hsp_send_ok(int rsock);
410 static int hsp_send_error(int rsock);
411 static int hsp_send_vgs(int rsock, int gain);
412 static int hsp_send_vgm(int rsock, int gain);
413 static int hsp_send_ring(int rsock);
414 
415 
416 /*
417  * Hayes AT command helpers
418  */
419 typedef enum {
420  /* errors */
424  /* at responses */
436  /* at commands */
454 } at_message_t;
455 
456 static int at_match_prefix(char *buf, char *prefix);
457 static at_message_t at_read_full(int rsock, char *buf, size_t count);
458 static inline const char *at_msg2str(at_message_t msg);
459 
463  void *data;
464 
466 };
467 
468 static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to);
469 static int msg_queue_push_data(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to, void *data);
470 static struct msg_queue_entry *msg_queue_pop(struct mbl_pvt *pvt);
471 static void msg_queue_free_and_pop(struct mbl_pvt *pvt);
472 static void msg_queue_flush(struct mbl_pvt *pvt);
473 static struct msg_queue_entry *msg_queue_head(struct mbl_pvt *pvt);
474 
475 /*
476  * channel stuff
477  */
478 
479 static struct ast_channel_tech mbl_tech = {
480  .type = "Mobile",
481  .description = "Bluetooth Mobile Device Channel Driver",
482  .requester = mbl_request,
483  .call = mbl_call,
484  .hangup = mbl_hangup,
485  .answer = mbl_answer,
486  .send_digit_end = mbl_digit_end,
487  .read = mbl_read,
488  .write = mbl_write,
489  .fixup = mbl_fixup,
490  .devicestate = mbl_devicestate
491 };
492 
493 /* CLI Commands implementation */
494 
495 static char *handle_cli_mobile_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
496 {
497  struct mbl_pvt *pvt;
498  char bdaddr[18];
499  char group[6];
500 
501 #define FORMAT1 "%-15.15s %-17.17s %-5.5s %-15.15s %-9.9s %-10.10s %-3.3s\n"
502 
503  switch (cmd) {
504  case CLI_INIT:
505  e->command = "mobile show devices";
506  e->usage =
507  "Usage: mobile show devices\n"
508  " Shows the state of Bluetooth Cell / Mobile devices.\n";
509  return NULL;
510  case CLI_GENERATE:
511  return NULL;
512  }
513 
514  if (a->argc != 3)
515  return CLI_SHOWUSAGE;
516 
517  ast_cli(a->fd, FORMAT1, "ID", "Address", "Group", "Adapter", "Connected", "State", "SMS");
520  ast_mutex_lock(&pvt->lock);
521  ba2str(&pvt->addr, bdaddr);
522  snprintf(group, sizeof(group), "%d", pvt->group);
523  ast_cli(a->fd, FORMAT1,
524  pvt->id,
525  bdaddr,
526  group,
527  pvt->adapter->id,
528  pvt->connected ? "Yes" : "No",
529  (!pvt->connected) ? "None" : (pvt->owner) ? "Busy" : (pvt->outgoing_sms || pvt->incoming_sms) ? "SMS" : (mbl_has_service(pvt)) ? "Free" : "No Service",
530  (pvt->has_sms) ? "Yes" : "No"
531  );
532  ast_mutex_unlock(&pvt->lock);
533  }
535 
536 #undef FORMAT1
537 
538  return CLI_SUCCESS;
539 }
540 
541 static char *handle_cli_mobile_search(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
542 {
543  struct adapter_pvt *adapter;
544  inquiry_info *ii = NULL;
545  int max_rsp, num_rsp;
546  int len, flags;
547  int i, phport, hsport;
548  char addr[19] = {0};
549  char name[31] = {0};
550 
551 #define FORMAT1 "%-17.17s %-30.30s %-6.6s %-7.7s %-4.4s\n"
552 #define FORMAT2 "%-17.17s %-30.30s %-6.6s %-7.7s %d\n"
553 
554  switch (cmd) {
555  case CLI_INIT:
556  e->command = "mobile search";
557  e->usage =
558  "Usage: mobile search\n"
559  " Searches for Bluetooth Cell / Mobile devices in range.\n";
560  return NULL;
561  case CLI_GENERATE:
562  return NULL;
563  }
564 
565  if (a->argc != 2)
566  return CLI_SHOWUSAGE;
567 
568  /* find a free adapter */
570  AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
571  if (!adapter->inuse)
572  break;
573  }
575 
576  if (!adapter) {
577  ast_cli(a->fd, "All Bluetooth adapters are in use at this time.\n");
578  return CLI_SUCCESS;
579  }
580 
581  len = 8;
582  max_rsp = 255;
583  flags = IREQ_CACHE_FLUSH;
584 
585  ii = ast_alloca(max_rsp * sizeof(inquiry_info));
586  num_rsp = hci_inquiry(adapter->dev_id, len, max_rsp, NULL, &ii, flags);
587  if (num_rsp > 0) {
588  ast_cli(a->fd, FORMAT1, "Address", "Name", "Usable", "Type", "Port");
589  for (i = 0; i < num_rsp; i++) {
590  ba2str(&(ii + i)->bdaddr, addr);
591  name[0] = 0x00;
592  if (hci_read_remote_name(adapter->hci_socket, &(ii + i)->bdaddr, sizeof(name) - 1, name, 0) < 0)
593  strcpy(name, "[unknown]");
594  phport = sdp_search(addr, HANDSFREE_AGW_PROFILE_ID);
595  if (!phport)
596  hsport = sdp_search(addr, HEADSET_PROFILE_ID);
597  else
598  hsport = 0;
599  ast_cli(a->fd, FORMAT2, addr, name, (phport > 0 || hsport > 0) ? "Yes" : "No",
600  (phport > 0) ? "Phone" : "Headset", (phport > 0) ? phport : hsport);
601  }
602  } else
603  ast_cli(a->fd, "No Bluetooth Cell / Mobile devices found.\n");
604 
605 #undef FORMAT1
606 #undef FORMAT2
607 
608  return CLI_SUCCESS;
609 }
610 
611 static char *handle_cli_mobile_rfcomm(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
612 {
613  char buf[128];
614  struct mbl_pvt *pvt = NULL;
615 
616  switch (cmd) {
617  case CLI_INIT:
618  e->command = "mobile rfcomm";
619  e->usage =
620  "Usage: mobile rfcomm <device ID> <command>\n"
621  " Send <command> to the rfcomm port on the device\n"
622  " with the specified <device ID>.\n";
623  return NULL;
624  case CLI_GENERATE:
625  return NULL;
626  }
627 
628  if (a->argc != 4)
629  return CLI_SHOWUSAGE;
630 
633  if (!strcmp(pvt->id, a->argv[2]))
634  break;
635  }
637 
638  if (!pvt) {
639  ast_cli(a->fd, "Device %s not found.\n", a->argv[2]);
640  goto e_return;
641  }
642 
643  ast_mutex_lock(&pvt->lock);
644  if (!pvt->connected) {
645  ast_cli(a->fd, "Device %s not connected.\n", a->argv[2]);
646  goto e_unlock_pvt;
647  }
648 
649  snprintf(buf, sizeof(buf), "%s\r", a->argv[3]);
650  rfcomm_write(pvt->rfcomm_socket, buf);
652 
653 e_unlock_pvt:
654  ast_mutex_unlock(&pvt->lock);
655 e_return:
656  return CLI_SUCCESS;
657 }
658 
659 static char *handle_cli_mobile_cusd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
660 {
661  char buf[128];
662  struct mbl_pvt *pvt = NULL;
663 
664  switch (cmd) {
665  case CLI_INIT:
666  e->command = "mobile cusd";
667  e->usage =
668  "Usage: mobile cusd <device ID> <command>\n"
669  " Send cusd <command> to the rfcomm port on the device\n"
670  " with the specified <device ID>.\n";
671  return NULL;
672  case CLI_GENERATE:
673  return NULL;
674  }
675 
676  if (a->argc != 4)
677  return CLI_SHOWUSAGE;
678 
681  if (!strcmp(pvt->id, a->argv[2]))
682  break;
683  }
685 
686  if (!pvt) {
687  ast_cli(a->fd, "Device %s not found.\n", a->argv[2]);
688  goto e_return;
689  }
690 
691  ast_mutex_lock(&pvt->lock);
692  if (!pvt->connected) {
693  ast_cli(a->fd, "Device %s not connected.\n", a->argv[2]);
694  goto e_unlock_pvt;
695  }
696 
697  snprintf(buf, sizeof(buf), "%s", a->argv[3]);
698  if (hfp_send_cusd(pvt->hfp, buf) || msg_queue_push(pvt, AT_OK, AT_CUSD)) {
699  ast_cli(a->fd, "[%s] error sending CUSD\n", pvt->id);
700  goto e_unlock_pvt;
701  }
702 
703 e_unlock_pvt:
704  ast_mutex_unlock(&pvt->lock);
705 e_return:
706  return CLI_SUCCESS;
707 }
708 
709 /*
710 
711  Dialplan applications implementation
712 
713 */
714 
715 static int mbl_status_exec(struct ast_channel *ast, const char *data)
716 {
717 
718  struct mbl_pvt *pvt;
719  char *parse;
720  int stat;
721  char status[2];
722 
724  AST_APP_ARG(device);
725  AST_APP_ARG(variable);
726  );
727 
728  if (ast_strlen_zero(data))
729  return -1;
730 
731  parse = ast_strdupa(data);
732 
733  AST_STANDARD_APP_ARGS(args, parse);
734 
735  if (ast_strlen_zero(args.device) || ast_strlen_zero(args.variable))
736  return -1;
737 
738  stat = 1;
739 
742  if (!strcmp(pvt->id, args.device))
743  break;
744  }
746 
747  if (pvt) {
748  ast_mutex_lock(&pvt->lock);
749  if (pvt->connected)
750  stat = 2;
751  if (pvt->owner)
752  stat = 3;
753  ast_mutex_unlock(&pvt->lock);
754  }
755 
756  snprintf(status, sizeof(status), "%d", stat);
757  pbx_builtin_setvar_helper(ast, args.variable, status);
758 
759  return 0;
760 
761 }
762 
763 static int mbl_sendsms_exec(struct ast_channel *ast, const char *data)
764 {
765 
766  struct mbl_pvt *pvt;
767  char *parse, *message;
768 
770  AST_APP_ARG(device);
771  AST_APP_ARG(dest);
772  AST_APP_ARG(message);
773  );
774 
775  if (ast_strlen_zero(data))
776  return -1;
777 
778  parse = ast_strdupa(data);
779 
780  AST_STANDARD_APP_ARGS(args, parse);
781 
782  if (ast_strlen_zero(args.device)) {
783  ast_log(LOG_ERROR,"NULL device for message -- SMS will not be sent.\n");
784  return -1;
785  }
786 
787  if (ast_strlen_zero(args.dest)) {
788  ast_log(LOG_ERROR,"NULL destination for message -- SMS will not be sent.\n");
789  return -1;
790  }
791 
792  if (ast_strlen_zero(args.message)) {
793  ast_log(LOG_ERROR,"NULL Message to be sent -- SMS will not be sent.\n");
794  return -1;
795  }
796 
799  if (!strcmp(pvt->id, args.device))
800  break;
801  }
803 
804  if (!pvt) {
805  ast_log(LOG_ERROR,"Bluetooth device %s wasn't found in the list -- SMS will not be sent.\n", args.device);
806  goto e_return;
807  }
808 
809  ast_mutex_lock(&pvt->lock);
810  if (!pvt->connected) {
811  ast_log(LOG_ERROR,"Bluetooth device %s wasn't connected -- SMS will not be sent.\n", args.device);
812  goto e_unlock_pvt;
813  }
814 
815  if (!pvt->has_sms) {
816  ast_log(LOG_ERROR,"Bluetooth device %s doesn't handle SMS -- SMS will not be sent.\n", args.device);
817  goto e_unlock_pvt;
818  }
819 
820  message = ast_strdup(args.message);
821 
822  if (hfp_send_cmgs(pvt->hfp, args.dest)
823  || msg_queue_push_data(pvt, AT_SMS_PROMPT, AT_CMGS, message)) {
824 
825  ast_log(LOG_ERROR, "[%s] problem sending SMS message\n", pvt->id);
826  goto e_free_message;
827  }
828 
829  ast_mutex_unlock(&pvt->lock);
830 
831  return 0;
832 
833 e_free_message:
834  ast_free(message);
835 e_unlock_pvt:
836  ast_mutex_unlock(&pvt->lock);
837 e_return:
838  return -1;
839 }
840 
841 /*
842 
843  Channel Driver callbacks
844 
845 */
846 
847 static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo,
848  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
849 {
850  struct ast_channel *chn;
851 
852  pvt->answered = 0;
853  pvt->alignment_count = 0;
855  if (pvt->adapter->alignment_detection)
856  pvt->do_alignment_detection = 1;
857  else
858  pvt->do_alignment_detection = 0;
859 
862  ast_dsp_digitreset(pvt->dsp);
863 
864  chn = ast_channel_alloc(1, state,
865  cidinfo ? cidinfo->cnum : NULL,
866  cidinfo ? cidinfo->cnam : NULL,
867  0, 0, pvt->context, assignedids, requestor, 0,
868  "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);
869  if (!chn) {
870  goto e_return;
871  }
872 
873  ast_channel_tech_set(chn, &mbl_tech);
879  ast_channel_tech_pvt_set(chn, pvt);
880 
881  if (state == AST_STATE_RING)
882  ast_channel_rings_set(chn, 1);
883 
884  ast_channel_language_set(chn, "en");
885  pvt->owner = chn;
886 
887  if (pvt->sco_socket != -1) {
888  ast_channel_set_fd(chn, 0, pvt->sco_socket);
889  }
890  ast_channel_unlock(chn);
891 
892  return chn;
893 
894 e_return:
895  return NULL;
896 }
897 
898 static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap,
899  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
900 {
901 
902  struct ast_channel *chn = NULL;
903  struct mbl_pvt *pvt;
904  char *dest_dev = NULL;
905  char *dest_num = NULL;
906  int group = -1;
907 
908  if (!data) {
909  ast_log(LOG_WARNING, "Channel requested with no data\n");
911  return NULL;
912  }
913 
915  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
916  ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
918  return NULL;
919  }
920 
921  dest_dev = ast_strdupa(data);
922 
923  dest_num = strchr(dest_dev, '/');
924  if (dest_num)
925  *dest_num++ = 0x00;
926 
927  if (((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) && ((dest_dev[1] >= '0') && (dest_dev[1] <= '9'))) {
928  group = atoi(&dest_dev[1]);
929  }
930 
931  /* Find requested device and make sure it's connected. */
934  if (group > -1 && pvt->group == group && pvt->connected && !pvt->owner) {
935  if (!mbl_has_service(pvt)) {
936  continue;
937  }
938 
939  break;
940  } else if (!strcmp(pvt->id, dest_dev)) {
941  break;
942  }
943  }
945  if (!pvt || !pvt->connected || pvt->owner) {
946  ast_log(LOG_WARNING, "Request to call on device %s which is not connected / already in use.\n", dest_dev);
948  return NULL;
949  }
950 
951  if ((pvt->type == MBL_TYPE_PHONE) && !dest_num) {
952  ast_log(LOG_WARNING, "Can't determine destination number.\n");
954  return NULL;
955  }
956 
957  ast_mutex_lock(&pvt->lock);
958  chn = mbl_new(AST_STATE_DOWN, pvt, NULL, assignedids, requestor);
959  ast_mutex_unlock(&pvt->lock);
960  if (!chn) {
961  ast_log(LOG_WARNING, "Unable to allocate channel structure.\n");
963  return NULL;
964  }
965 
966  return chn;
967 
968 }
969 
970 static int mbl_call(struct ast_channel *ast, const char *dest, int timeout)
971 {
972  struct mbl_pvt *pvt;
973  char *dest_dev;
974  char *dest_num = NULL;
975 
976  dest_dev = ast_strdupa(dest);
977 
978  pvt = ast_channel_tech_pvt(ast);
979 
980  if (pvt->type == MBL_TYPE_PHONE) {
981  dest_num = strchr(dest_dev, '/');
982  if (!dest_num) {
983  ast_log(LOG_WARNING, "Cant determine destination number.\n");
984  return -1;
985  }
986  *dest_num++ = 0x00;
987  }
988 
990  ast_log(LOG_WARNING, "mbl_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
991  return -1;
992  }
993 
994  ast_debug(1, "Calling %s on %s\n", dest, ast_channel_name(ast));
995 
996  ast_mutex_lock(&pvt->lock);
997  if (pvt->type == MBL_TYPE_PHONE) {
998  if (hfp_send_atd(pvt->hfp, dest_num)) {
999  ast_mutex_unlock(&pvt->lock);
1000  ast_log(LOG_ERROR, "error sending ATD command on %s\n", pvt->id);
1001  return -1;
1002  }
1003  pvt->hangupcause = 0;
1004  pvt->needchup = 1;
1005  msg_queue_push(pvt, AT_OK, AT_D);
1006  } else {
1007  if (hsp_send_ring(pvt->rfcomm_socket)) {
1008  ast_log(LOG_ERROR, "[%s] error ringing device\n", pvt->id);
1009  ast_mutex_unlock(&pvt->lock);
1010  return -1;
1011  }
1012 
1013  if ((pvt->ring_sched_id = ast_sched_add(pvt->sched, 6000, headset_send_ring, pvt)) == -1) {
1014  ast_log(LOG_ERROR, "[%s] error ringing device\n", pvt->id);
1015  ast_mutex_unlock(&pvt->lock);
1016  return -1;
1017  }
1018 
1019  pvt->outgoing = 1;
1020  pvt->needring = 1;
1021  }
1022  ast_mutex_unlock(&pvt->lock);
1023 
1024  return 0;
1025 
1026 }
1027 
1028 static int mbl_hangup(struct ast_channel *ast)
1029 {
1030 
1031  struct mbl_pvt *pvt;
1032 
1033  if (!ast_channel_tech_pvt(ast)) {
1034  ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
1035  return 0;
1036  }
1037  pvt = ast_channel_tech_pvt(ast);
1038 
1039  ast_debug(1, "[%s] hanging up device\n", pvt->id);
1040 
1041  ast_mutex_lock(&pvt->lock);
1042  ast_channel_set_fd(ast, 0, -1);
1043  close(pvt->sco_socket);
1044  pvt->sco_socket = -1;
1045 
1046  if (pvt->needchup) {
1047  hfp_send_chup(pvt->hfp);
1048  msg_queue_push(pvt, AT_OK, AT_CHUP);
1049  pvt->needchup = 0;
1050  }
1051 
1052  pvt->outgoing = 0;
1053  pvt->incoming = 0;
1054  pvt->needring = 0;
1055  pvt->owner = NULL;
1057 
1058  ast_mutex_unlock(&pvt->lock);
1059 
1061 
1062  return 0;
1063 
1064 }
1065 
1066 static int mbl_answer(struct ast_channel *ast)
1067 {
1068 
1069  struct mbl_pvt *pvt;
1070 
1071  pvt = ast_channel_tech_pvt(ast);
1072 
1073  if (pvt->type == MBL_TYPE_HEADSET)
1074  return 0;
1075 
1076  ast_mutex_lock(&pvt->lock);
1077  if (pvt->incoming) {
1078  hfp_send_ata(pvt->hfp);
1079  msg_queue_push(pvt, AT_OK, AT_A);
1080  pvt->answered = 1;
1081  }
1082  ast_mutex_unlock(&pvt->lock);
1083 
1084  return 0;
1085 
1086 }
1087 
1088 static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
1089 {
1090  struct mbl_pvt *pvt = ast_channel_tech_pvt(ast);
1091 
1092  if (pvt->type == MBL_TYPE_HEADSET)
1093  return 0;
1094 
1095  ast_mutex_lock(&pvt->lock);
1096  if (hfp_send_dtmf(pvt->hfp, digit)) {
1097  ast_mutex_unlock(&pvt->lock);
1098  ast_debug(1, "[%s] error sending digit %c\n", pvt->id, digit);
1099  return -1;
1100  }
1101  msg_queue_push(pvt, AT_OK, AT_VTS);
1102  ast_mutex_unlock(&pvt->lock);
1103 
1104  ast_debug(1, "[%s] dialed %c\n", pvt->id, digit);
1105 
1106  return 0;
1107 }
1108 
1109 static struct ast_frame *mbl_read(struct ast_channel *ast)
1110 {
1111 
1112  struct mbl_pvt *pvt = ast_channel_tech_pvt(ast);
1113  struct ast_frame *fr = &ast_null_frame;
1114  int r;
1115 
1116  ast_debug(3, "*** mbl_read()\n");
1117 
1118  while (ast_mutex_trylock(&pvt->lock)) {
1120  }
1121 
1122  if (!pvt->owner || pvt->sco_socket == -1) {
1123  goto e_return;
1124  }
1125 
1126  memset(&pvt->fr, 0x00, sizeof(struct ast_frame));
1127  pvt->fr.frametype = AST_FRAME_VOICE;
1129  pvt->fr.src = "Mobile";
1130  pvt->fr.offset = AST_FRIENDLY_OFFSET;
1131  pvt->fr.mallocd = 0;
1132  pvt->fr.delivery.tv_sec = 0;
1133  pvt->fr.delivery.tv_usec = 0;
1134  pvt->fr.data.ptr = pvt->io_buf + AST_FRIENDLY_OFFSET;
1135 
1136  do {
1137  if ((r = read(pvt->sco_socket, pvt->fr.data.ptr, DEVICE_FRAME_SIZE)) == -1) {
1138  if (errno != EAGAIN && errno != EINTR) {
1139  ast_debug(1, "[%s] read error %d, going to wait for new connection\n", pvt->id, errno);
1140  close(pvt->sco_socket);
1141  pvt->sco_socket = -1;
1142  ast_channel_set_fd(ast, 0, -1);
1143  }
1144  goto e_return;
1145  }
1146 
1147  pvt->fr.datalen = r;
1148  pvt->fr.samples = r / 2;
1149 
1150  if (pvt->do_alignment_detection)
1151  do_alignment_detection(pvt, pvt->fr.data.ptr, r);
1152 
1153  ast_smoother_feed(pvt->bt_in_smoother, &pvt->fr);
1154  fr = ast_smoother_read(pvt->bt_in_smoother);
1155  } while (fr == NULL);
1156  fr = ast_dsp_process(ast, pvt->dsp, fr);
1157 
1158  ast_mutex_unlock(&pvt->lock);
1159 
1160  return fr;
1161 
1162 e_return:
1163  ast_mutex_unlock(&pvt->lock);
1164  return fr;
1165 }
1166 
1167 static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)
1168 {
1169 
1170  struct mbl_pvt *pvt = ast_channel_tech_pvt(ast);
1171  struct ast_frame *f;
1172 
1173  ast_debug(3, "*** mbl_write\n");
1174 
1175  if (frame->frametype != AST_FRAME_VOICE) {
1176  return 0;
1177  }
1178 
1179  while (ast_mutex_trylock(&pvt->lock)) {
1181  }
1182 
1183  ast_smoother_feed(pvt->bt_out_smoother, frame);
1184 
1185  while ((f = ast_smoother_read(pvt->bt_out_smoother))) {
1186  sco_write(pvt->sco_socket, f->data.ptr, f->datalen);
1187  }
1188 
1189  ast_mutex_unlock(&pvt->lock);
1190 
1191  return 0;
1192 
1193 }
1194 
1195 static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1196 {
1197 
1198  struct mbl_pvt *pvt = ast_channel_tech_pvt(newchan);
1199 
1200  if (!pvt) {
1201  ast_debug(1, "fixup failed, no pvt on newchan\n");
1202  return -1;
1203  }
1204 
1205  ast_mutex_lock(&pvt->lock);
1206  if (pvt->owner == oldchan)
1207  pvt->owner = newchan;
1208  ast_mutex_unlock(&pvt->lock);
1209 
1210  return 0;
1211 
1212 }
1213 
1214 static int mbl_devicestate(const char *data)
1215 {
1216 
1217  char *device;
1218  int res = AST_DEVICE_INVALID;
1219  struct mbl_pvt *pvt;
1220 
1221  device = ast_strdupa(S_OR(data, ""));
1222 
1223  ast_debug(1, "Checking device state for device %s\n", device);
1224 
1227  if (!strcmp(pvt->id, device))
1228  break;
1229  }
1231 
1232  if (!pvt)
1233  return res;
1234 
1235  ast_mutex_lock(&pvt->lock);
1236  if (pvt->connected) {
1237  if (pvt->owner)
1238  res = AST_DEVICE_INUSE;
1239  else
1240  res = AST_DEVICE_NOT_INUSE;
1241 
1242  if (!mbl_has_service(pvt))
1243  res = AST_DEVICE_UNAVAILABLE;
1244  }
1245  ast_mutex_unlock(&pvt->lock);
1246 
1247  return res;
1248 
1249 }
1250 
1251 /*
1252 
1253  Callback helpers
1254 
1255 */
1256 
1257 /*
1258 
1259  do_alignment_detection()
1260 
1261  This routine attempts to detect where we get misaligned sco audio data from the bluetooth adaptor.
1262 
1263  Its enabled by alignmentdetect=yes under the adapter entry in mobile.conf
1264 
1265  Some adapters suffer a problem where occasionally they will byte shift the audio stream one byte to the right.
1266  The result is static or white noise on the inbound (from the adapter) leg of the call.
1267  This is characterised by a sudden jump in magnitude of the value of the 16 bit samples.
1268 
1269  Here we look at the first 4 48 byte frames. We average the absolute values of each sample in the frame,
1270  then average the sum of the averages of frames 1, 2, and 3.
1271  Frame zero is usually zero.
1272  If the end result > 100, and it usually is if we have the problem, set a flag and compensate by shifting the bytes
1273  for each subsequent frame during the call.
1274 
1275  If the result is <= 100 then clear the flag so we don't come back in here...
1276 
1277  This seems to work OK....
1278 
1279 */
1280 
1281 static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen)
1282 {
1283 
1284  int i;
1285  short a, *s;
1286  char *p;
1287 
1288  if (pvt->alignment_detection_triggered) {
1289  for (i=buflen, p=buf+buflen-1; i>0; i--, p--)
1290  *p = *(p-1);
1291  *(p+1) = 0;
1292  return;
1293  }
1294 
1295  if (pvt->alignment_count < 4) {
1296  s = (short *)buf;
1297  for (i=0, a=0; i<buflen/2; i++) {
1298  a += *s++;
1299  a /= i+1;
1300  }
1301  pvt->alignment_samples[pvt->alignment_count++] = a;
1302  return;
1303  }
1304 
1305  ast_debug(1, "Alignment Detection result is [%-d %-d %-d %-d]\n", pvt->alignment_samples[0], pvt->alignment_samples[1], pvt->alignment_samples[2], pvt->alignment_samples[3]);
1306 
1307  a = abs(pvt->alignment_samples[1]) + abs(pvt->alignment_samples[2]) + abs(pvt->alignment_samples[3]);
1308  a /= 3;
1309  if (a > 100) {
1311  ast_debug(1, "Alignment Detection Triggered.\n");
1312  } else
1313  pvt->do_alignment_detection = 0;
1314 
1315 }
1316 
1317 static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
1318 {
1319  for (;;) {
1320  if (pvt->owner) {
1321  if (ast_channel_trylock(pvt->owner)) {
1322  DEADLOCK_AVOIDANCE(&pvt->lock);
1323  } else {
1324  ast_queue_control(pvt->owner, control);
1325  ast_channel_unlock(pvt->owner);
1326  break;
1327  }
1328  } else
1329  break;
1330  }
1331  return 0;
1332 }
1333 
1334 static int mbl_queue_hangup(struct mbl_pvt *pvt)
1335 {
1336  for (;;) {
1337  if (pvt->owner) {
1338  if (ast_channel_trylock(pvt->owner)) {
1339  DEADLOCK_AVOIDANCE(&pvt->lock);
1340  } else {
1341  if (pvt->hangupcause != 0) {
1343  }
1344  ast_queue_hangup(pvt->owner);
1345  ast_channel_unlock(pvt->owner);
1346  break;
1347  }
1348  } else
1349  break;
1350  }
1351  return 0;
1352 }
1353 
1354 static int mbl_ast_hangup(struct mbl_pvt *pvt)
1355 {
1356  ast_hangup(pvt->owner);
1357  return 0;
1358 }
1359 
1360 /*!
1361  * \brief Check if a mobile device has service.
1362  * \param pvt a mbl_pvt struct
1363  * \retval 1 this device has service
1364  * \retval 0 no service
1365  *
1366  * \note This function will always indicate that service is available if the
1367  * given device does not support service indication.
1368  */
1369 static int mbl_has_service(struct mbl_pvt *pvt)
1370 {
1371 
1372  if (pvt->type != MBL_TYPE_PHONE)
1373  return 1;
1374 
1375  if (!pvt->hfp->cind_map.service)
1376  return 1;
1377 
1379  return 1;
1380 
1381  return 0;
1382 }
1383 
1384 /*
1385 
1386  rfcomm helpers
1387 
1388 */
1389 
1390 static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel)
1391 {
1392 
1393  struct sockaddr_rc addr;
1394  int s;
1395 
1396  if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
1397  ast_debug(1, "socket() failed (%d).\n", errno);
1398  return -1;
1399  }
1400 
1401  memset(&addr, 0, sizeof(addr));
1402  addr.rc_family = AF_BLUETOOTH;
1403  bacpy(&addr.rc_bdaddr, &src);
1404  addr.rc_channel = (uint8_t) 0;
1405  if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1406  ast_debug(1, "bind() failed (%d).\n", errno);
1407  close(s);
1408  return -1;
1409  }
1410 
1411  memset(&addr, 0, sizeof(addr));
1412  addr.rc_family = AF_BLUETOOTH;
1413  bacpy(&addr.rc_bdaddr, &dst);
1414  addr.rc_channel = remote_channel;
1415  if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1416  ast_debug(1, "connect() failed (%d).\n", errno);
1417  close(s);
1418  return -1;
1419  }
1420 
1421  return s;
1422 
1423 }
1424 
1425 /*!
1426  * \brief Write to an rfcomm socket.
1427  * \param rsock the socket to write to
1428  * \param buf the null terminated buffer to write
1429  *
1430  * This function will write characters from buf. The buffer must be null
1431  * terminated.
1432  *
1433  * \retval -1 error
1434  * \retval 0 success
1435  */
1436 static int rfcomm_write(int rsock, char *buf)
1437 {
1438  return rfcomm_write_full(rsock, buf, strlen(buf));
1439 }
1440 
1441 
1442 /*!
1443  * \brief Write to an rfcomm socket.
1444  * \param rsock the socket to write to
1445  * \param buf the buffer to write
1446  * \param count the number of characters from the buffer to write
1447  *
1448  * This function will write count characters from buf. It will always write
1449  * count chars unless it encounters an error.
1450  *
1451  * \retval -1 error
1452  * \retval 0 success
1453  */
1454 static int rfcomm_write_full(int rsock, char *buf, size_t count)
1455 {
1456  char *p = buf;
1457  ssize_t out_count;
1458 
1459  ast_debug(1, "rfcomm_write() (%d) [%.*s]\n", rsock, (int) count, buf);
1460  while (count > 0) {
1461  if ((out_count = write(rsock, p, count)) == -1) {
1462  ast_debug(1, "rfcomm_write() error [%d]\n", errno);
1463  return -1;
1464  }
1465  count -= out_count;
1466  p += out_count;
1467  }
1468 
1469  return 0;
1470 }
1471 
1472 /*!
1473  * \brief Wait for activity on an rfcomm socket.
1474  * \param rsock the socket to watch
1475  * \param ms a pointer to an int containing a timeout in ms
1476  * \return zero on timeout and the socket fd (non-zero) otherwise
1477  * \retval 0 timeout
1478  */
1479 static int rfcomm_wait(int rsock, int *ms)
1480 {
1481  int exception, outfd;
1482  outfd = ast_waitfor_n_fd(&rsock, 1, ms, &exception);
1483  if (outfd < 0)
1484  outfd = 0;
1485 
1486  return outfd;
1487 }
1488 
1489 #ifdef RFCOMM_READ_DEBUG
1490 #define rfcomm_read_debug(c) __rfcomm_read_debug(c)
1491 static void __rfcomm_read_debug(char c)
1492 {
1493  if (c == '\r')
1494  ast_debug(2, "rfcomm_read: \\r\n");
1495  else if (c == '\n')
1496  ast_debug(2, "rfcomm_read: \\n\n");
1497  else
1498  ast_debug(2, "rfcomm_read: %c\n", c);
1499 }
1500 #else
1501 #define rfcomm_read_debug(c)
1502 #endif
1503 
1504 /*!
1505  * \brief Append the given character to the given buffer and increase the
1506  * in_count.
1507  */
1508 static void inline rfcomm_append_buf(char **buf, size_t count, size_t *in_count, char c)
1509 {
1510  if (*in_count < count) {
1511  (*in_count)++;
1512  *(*buf)++ = c;
1513  }
1514 }
1515 
1516 /*!
1517  * \brief Read a character from the given stream and check if it matches what
1518  * we expected.
1519  */
1520 static int rfcomm_read_and_expect_char(int rsock, char *result, char expected)
1521 {
1522  int res;
1523  char c;
1524 
1525  if (!result)
1526  result = &c;
1527 
1528  if ((res = read(rsock, result, 1)) < 1) {
1529  return res;
1530  }
1531  rfcomm_read_debug(*result);
1532 
1533  if (*result != expected) {
1534  return -2;
1535  }
1536 
1537  return 1;
1538 }
1539 
1540 /*!
1541  * \brief Read a character from the given stream and append it to the given
1542  * buffer if it matches the expected character.
1543  */
1544 static int rfcomm_read_and_append_char(int rsock, char **buf, size_t count, size_t *in_count, char *result, char expected)
1545 {
1546  int res;
1547  char c;
1548 
1549  if (!result)
1550  result = &c;
1551 
1552  if ((res = rfcomm_read_and_expect_char(rsock, result, expected)) < 1) {
1553  return res;
1554  }
1555 
1556  rfcomm_append_buf(buf, count, in_count, *result);
1557  return 1;
1558 }
1559 
1560 /*!
1561  * \brief Read until \verbatim '\r\n'. \endverbatim
1562  * This function consumes the \verbatim'\r\n'\endverbatim but does not add it to buf.
1563  */
1564 static int rfcomm_read_until_crlf(int rsock, char **buf, size_t count, size_t *in_count)
1565 {
1566  int res;
1567  char c;
1568 
1569  while ((res = read(rsock, &c, 1)) == 1) {
1570  rfcomm_read_debug(c);
1571  if (c == '\r') {
1572  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\n')) == 1) {
1573  break;
1574  } else if (res == -2) {
1575  rfcomm_append_buf(buf, count, in_count, '\r');
1576  } else {
1577  rfcomm_append_buf(buf, count, in_count, '\r');
1578  break;
1579  }
1580  }
1581 
1582  rfcomm_append_buf(buf, count, in_count, c);
1583  }
1584  return res;
1585 }
1586 
1587 /*!
1588  * \brief Read the remainder of an AT SMS prompt.
1589  * \note the entire parsed string is \verbatim '\r\n> ' \endverbatim
1590  *
1591  * By the time this function is executed, only a ' ' is left to read.
1592  */
1593 static int rfcomm_read_sms_prompt(int rsock, char **buf, size_t count, size_t *in_count)
1594 {
1595  int res;
1596  if ((res = rfcomm_read_and_append_char(rsock, buf, count, in_count, NULL, ' ')) < 1)
1597  goto e_return;
1598 
1599  return 1;
1600 
1601 e_return:
1602  ast_log(LOG_ERROR, "error parsing SMS prompt on rfcomm socket\n");
1603  return res;
1604 }
1605 
1606 /*!
1607  * \brief Read until a \verbatim \r\nOK\r\n \endverbatim message.
1608  */
1609 static int rfcomm_read_until_ok(int rsock, char **buf, size_t count, size_t *in_count)
1610 {
1611  int res;
1612  char c;
1613 
1614  /* here, we read until finding a \r\n, then we read one character at a
1615  * time looking for the string '\r\nOK\r\n'. If we only find a partial
1616  * match, we place that in the buffer and try again. */
1617 
1618  for (;;) {
1619  if ((res = rfcomm_read_until_crlf(rsock, buf, count, in_count)) != 1) {
1620  break;
1621  }
1622 
1623  rfcomm_append_buf(buf, count, in_count, '\r');
1624  rfcomm_append_buf(buf, count, in_count, '\n');
1625 
1626  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\r')) != 1) {
1627  if (res != -2) {
1628  break;
1629  }
1630 
1631  rfcomm_append_buf(buf, count, in_count, c);
1632  continue;
1633  }
1634 
1635  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\n')) != 1) {
1636  if (res != -2) {
1637  break;
1638  }
1639 
1640  rfcomm_append_buf(buf, count, in_count, '\r');
1641  rfcomm_append_buf(buf, count, in_count, c);
1642  continue;
1643  }
1644  if ((res = rfcomm_read_and_expect_char(rsock, &c, 'O')) != 1) {
1645  if (res != -2) {
1646  break;
1647  }
1648 
1649  rfcomm_append_buf(buf, count, in_count, '\r');
1650  rfcomm_append_buf(buf, count, in_count, '\n');
1651  rfcomm_append_buf(buf, count, in_count, c);
1652  continue;
1653  }
1654 
1655  if ((res = rfcomm_read_and_expect_char(rsock, &c, 'K')) != 1) {
1656  if (res != -2) {
1657  break;
1658  }
1659 
1660  rfcomm_append_buf(buf, count, in_count, '\r');
1661  rfcomm_append_buf(buf, count, in_count, '\n');
1662  rfcomm_append_buf(buf, count, in_count, 'O');
1663  rfcomm_append_buf(buf, count, in_count, c);
1664  continue;
1665  }
1666 
1667  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\r')) != 1) {
1668  if (res != -2) {
1669  break;
1670  }
1671 
1672  rfcomm_append_buf(buf, count, in_count, '\r');
1673  rfcomm_append_buf(buf, count, in_count, '\n');
1674  rfcomm_append_buf(buf, count, in_count, 'O');
1675  rfcomm_append_buf(buf, count, in_count, 'K');
1676  rfcomm_append_buf(buf, count, in_count, c);
1677  continue;
1678  }
1679 
1680  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\n')) != 1) {
1681  if (res != -2) {
1682  break;
1683  }
1684 
1685  rfcomm_append_buf(buf, count, in_count, '\r');
1686  rfcomm_append_buf(buf, count, in_count, '\n');
1687  rfcomm_append_buf(buf, count, in_count, 'O');
1688  rfcomm_append_buf(buf, count, in_count, 'K');
1689  rfcomm_append_buf(buf, count, in_count, '\r');
1690  rfcomm_append_buf(buf, count, in_count, c);
1691  continue;
1692  }
1693 
1694  /* we have successfully parsed a '\r\nOK\r\n' string */
1695  return 1;
1696  }
1697 
1698  return res;
1699 }
1700 
1701 
1702 /*!
1703  * \brief Read the remainder of a +CMGR message.
1704  * \note the entire parsed string is \verbatim '+CMGR: ...\r\n...\r\n...\r\n...\r\nOK\r\n' \endverbatim
1705  */
1706 static int rfcomm_read_cmgr(int rsock, char **buf, size_t count, size_t *in_count)
1707 {
1708  int res;
1709 
1710  /* append the \r\n that was stripped by the calling function */
1711  rfcomm_append_buf(buf, count, in_count, '\r');
1712  rfcomm_append_buf(buf, count, in_count, '\n');
1713 
1714  if ((res = rfcomm_read_until_ok(rsock, buf, count, in_count)) != 1) {
1715  ast_log(LOG_ERROR, "error reading +CMGR message on rfcomm socket\n");
1716  }
1717 
1718  return res;
1719 }
1720 
1721 /*!
1722  * \brief Read and AT result code.
1723  * \note the entire parsed string is \verbatim '\r\n<result code>\r\n' \endverbatim
1724  */
1725 static int rfcomm_read_result(int rsock, char **buf, size_t count, size_t *in_count)
1726 {
1727  int res;
1728  char c;
1729 
1730  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\n')) < 1) {
1731  goto e_return;
1732  }
1733 
1734  if ((res = rfcomm_read_and_append_char(rsock, buf, count, in_count, &c, '>')) == 1) {
1735  return rfcomm_read_sms_prompt(rsock, buf, count, in_count);
1736  } else if (res != -2) {
1737  goto e_return;
1738  }
1739 
1740  rfcomm_append_buf(buf, count, in_count, c);
1741  res = rfcomm_read_until_crlf(rsock, buf, count, in_count);
1742 
1743  if (res != 1)
1744  return res;
1745 
1746  /* check for CMGR, which contains an embedded \r\n pairs terminated by
1747  * an \r\nOK\r\n message */
1748  if (*in_count >= 5 && !strncmp(*buf - *in_count, "+CMGR", 5)) {
1749  return rfcomm_read_cmgr(rsock, buf, count, in_count);
1750  }
1751 
1752  return 1;
1753 
1754 e_return:
1755  ast_log(LOG_ERROR, "error parsing AT result on rfcomm socket\n");
1756  return res;
1757 }
1758 
1759 /*!
1760  * \brief Read the remainder of an AT command.
1761  * \note the entire parsed string is \verbatim '<at command>\r' \endverbatim
1762  */
1763 static int rfcomm_read_command(int rsock, char **buf, size_t count, size_t *in_count)
1764 {
1765  int res;
1766  char c;
1767 
1768  while ((res = read(rsock, &c, 1)) == 1) {
1769  rfcomm_read_debug(c);
1770  /* stop when we get to '\r' */
1771  if (c == '\r')
1772  break;
1773 
1774  rfcomm_append_buf(buf, count, in_count, c);
1775  }
1776  return res;
1777 }
1778 
1779 /*!
1780  * \brief Read one Hayes AT message from an rfcomm socket.
1781  * \param rsock the rfcomm socket to read from
1782  * \param buf the buffer to store the result in
1783  * \param count the size of the buffer or the maximum number of characters to read
1784  *
1785  * Here we need to read complete Hayes AT messages. The AT message formats we
1786  * support are listed below.
1787  *
1788  * \verbatim
1789  * \r\n<result code>\r\n
1790  * <at command>\r
1791  * \r\n>
1792  * \endverbatim
1793  *
1794  * These formats correspond to AT result codes, AT commands, and the AT SMS
1795  * prompt respectively. When messages are read the leading and trailing \verbatim '\r' \endverbatim
1796  * and \verbatim '\n' \endverbatim characters are discarded. If the given buffer is not large enough
1797  * to hold the response, what does not fit in the buffer will be dropped.
1798  *
1799  * \note The rfcomm connection to the device is asynchronous, so there is no
1800  * guarantee that responses will be returned in a single read() call. We handle
1801  * this by blocking until we can read an entire response.
1802  *
1803  * \retval 0 end of file
1804  * \retval -1 read error
1805  * \retval -2 parse error
1806  * \retval other the number of characters added to buf
1807  */
1808 static ssize_t rfcomm_read(int rsock, char *buf, size_t count)
1809 {
1810  ssize_t res;
1811  size_t in_count = 0;
1812  char c;
1813 
1814  if ((res = rfcomm_read_and_expect_char(rsock, &c, '\r')) == 1) {
1815  res = rfcomm_read_result(rsock, &buf, count, &in_count);
1816  } else if (res == -2) {
1817  rfcomm_append_buf(&buf, count, &in_count, c);
1818  res = rfcomm_read_command(rsock, &buf, count, &in_count);
1819  }
1820 
1821  if (res < 1)
1822  return res;
1823  else
1824  return in_count;
1825 }
1826 
1827 /*
1828 
1829  sco helpers and callbacks
1830 
1831 */
1832 
1833 static int sco_connect(bdaddr_t src, bdaddr_t dst)
1834 {
1835 
1836  struct sockaddr_sco addr;
1837  int s;
1838 
1839  if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
1840  ast_debug(1, "socket() failed (%d).\n", errno);
1841  return -1;
1842  }
1843 
1844 /* XXX this does not work with the do_sco_listen() thread (which also bind()s
1845  * to this address). Also I am not sure if it is necessary. */
1846 #if 0
1847  memset(&addr, 0, sizeof(addr));
1848  addr.sco_family = AF_BLUETOOTH;
1849  bacpy(&addr.sco_bdaddr, &src);
1850  if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1851  ast_debug(1, "bind() failed (%d).\n", errno);
1852  close(s);
1853  return -1;
1854  }
1855 #endif
1856 
1857  memset(&addr, 0, sizeof(addr));
1858  addr.sco_family = AF_BLUETOOTH;
1859  bacpy(&addr.sco_bdaddr, &dst);
1860 
1861  if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1862  ast_debug(1, "sco connect() failed (%d).\n", errno);
1863  close(s);
1864  return -1;
1865  }
1866 
1867  return s;
1868 
1869 }
1870 
1871 static int sco_write(int s, char *buf, int len)
1872 {
1873 
1874  int r;
1875 
1876  if (s == -1) {
1877  ast_debug(3, "sco_write() not ready\n");
1878  return 0;
1879  }
1880 
1881  ast_debug(3, "sco_write()\n");
1882 
1883  r = write(s, buf, len);
1884  if (r == -1) {
1885  ast_debug(3, "sco write error %d\n", errno);
1886  return 0;
1887  }
1888 
1889  return 1;
1890 
1891 }
1892 
1893 /*!
1894  * \brief Accept SCO connections.
1895  * This function is an ast_io callback function used to accept incoming sco
1896  * audio connections.
1897  */
1898 static int sco_accept(int *id, int fd, short events, void *data)
1899 {
1900  struct adapter_pvt *adapter = (struct adapter_pvt *) data;
1901  struct sockaddr_sco addr;
1902  socklen_t addrlen;
1903  struct mbl_pvt *pvt;
1904  socklen_t len;
1905  char saddr[18];
1906  struct sco_options so;
1907  int sock;
1908 
1909  addrlen = sizeof(struct sockaddr_sco);
1910  if ((sock = accept(fd, (struct sockaddr *)&addr, &addrlen)) == -1) {
1911  ast_log(LOG_ERROR, "error accepting audio connection on adapter %s\n", adapter->id);
1912  return 0;
1913  }
1914 
1915  len = sizeof(so);
1916  getsockopt(sock, SOL_SCO, SCO_OPTIONS, &so, &len);
1917 
1918  ba2str(&addr.sco_bdaddr, saddr);
1919  ast_debug(1, "Incoming Audio Connection from device %s MTU is %d\n", saddr, so.mtu);
1920 
1921  /* figure out which device this sco connection belongs to */
1922  pvt = NULL;
1925  if (!bacmp(&pvt->addr, &addr.sco_bdaddr))
1926  break;
1927  }
1929  if (!pvt) {
1930  ast_log(LOG_WARNING, "could not find device for incoming audio connection\n");
1931  close(sock);
1932  return 1;
1933  }
1934 
1935  ast_mutex_lock(&pvt->lock);
1936  if (pvt->sco_socket != -1) {
1937  close(pvt->sco_socket);
1938  pvt->sco_socket = -1;
1939  }
1940 
1941  pvt->sco_socket = sock;
1942  if (pvt->owner) {
1943  ast_channel_set_fd(pvt->owner, 0, sock);
1944  } else {
1945  ast_debug(1, "incoming audio connection for pvt without owner\n");
1946  }
1947 
1948  ast_mutex_unlock(&pvt->lock);
1949 
1950  return 1;
1951 }
1952 
1953 /*!
1954  * \brief Bind an SCO listener socket for the given adapter.
1955  * \param adapter an adapter_pvt
1956  * \return -1 on error, non zero on success
1957  */
1958 static int sco_bind(struct adapter_pvt *adapter)
1959 {
1960  struct sockaddr_sco addr;
1961  int opt = 1;
1962 
1963  if ((adapter->sco_socket = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
1964  ast_log(LOG_ERROR, "Unable to create sco listener socket for adapter %s.\n", adapter->id);
1965  goto e_return;
1966  }
1967 
1968  memset(&addr, 0, sizeof(addr));
1969  addr.sco_family = AF_BLUETOOTH;
1970  bacpy(&addr.sco_bdaddr, &adapter->addr);
1971  if (bind(adapter->sco_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1972  ast_log(LOG_ERROR, "Unable to bind sco listener socket. (%d)\n", errno);
1973  goto e_close_socket;
1974  }
1975  if (setsockopt(adapter->sco_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
1976  ast_log(LOG_ERROR, "Unable to setsockopt sco listener socket.\n");
1977  goto e_close_socket;
1978  }
1979  if (listen(adapter->sco_socket, 5) < 0) {
1980  ast_log(LOG_ERROR, "Unable to listen sco listener socket.\n");
1981  goto e_close_socket;
1982  }
1983 
1984  return adapter->sco_socket;
1985 
1986 e_close_socket:
1987  close(adapter->sco_socket);
1988  adapter->sco_socket = -1;
1989 e_return:
1990  return -1;
1991 }
1992 
1993 
1994 /*
1995  * Hayes AT command helpers.
1996  */
1997 
1998 /*!
1999  * \brief Match the given buffer with the given prefix.
2000  * \param buf the buffer to match
2001  * \param prefix the prefix to match
2002  */
2003 static int at_match_prefix(char *buf, char *prefix)
2004 {
2005  return !strncmp(buf, prefix, strlen(prefix));
2006 }
2007 
2008 /*!
2009  * \brief Read an AT message and clasify it.
2010  * \param rsock an rfcomm socket
2011  * \param buf the buffer to store the result in
2012  * \param count the size of the buffer or the maximum number of characters to read
2013  * \return the type of message received, in addition buf will contain the
2014  * message received and will be null terminated
2015  * \see at_read()
2016  */
2017 static at_message_t at_read_full(int rsock, char *buf, size_t count)
2018 {
2019  ssize_t s;
2020  if ((s = rfcomm_read(rsock, buf, count - 1)) < 1)
2021  return s;
2022  buf[s] = '\0';
2023 
2024  if (!strcmp("OK", buf)) {
2025  return AT_OK;
2026  } else if (!strcmp("ERROR", buf)) {
2027  return AT_ERROR;
2028  } else if (!strcmp("RING", buf)) {
2029  return AT_RING;
2030  } else if (!strcmp("AT+CKPD=200", buf)) {
2031  return AT_CKPD;
2032  } else if (!strcmp("> ", buf)) {
2033  return AT_SMS_PROMPT;
2034  } else if (at_match_prefix(buf, "+CMTI:")) {
2035  return AT_CMTI;
2036  } else if (at_match_prefix(buf, "+CIEV:")) {
2037  return AT_CIEV;
2038  } else if (at_match_prefix(buf, "+BRSF:")) {
2039  return AT_BRSF;
2040  } else if (at_match_prefix(buf, "+CIND:")) {
2041  return AT_CIND;
2042  } else if (at_match_prefix(buf, "+CLIP:")) {
2043  return AT_CLIP;
2044  } else if (at_match_prefix(buf, "+CMGR:")) {
2045  return AT_CMGR;
2046  } else if (at_match_prefix(buf, "+VGM:")) {
2047  return AT_VGM;
2048  } else if (at_match_prefix(buf, "+VGS:")) {
2049  return AT_VGS;
2050  } else if (at_match_prefix(buf, "+CMS ERROR:")) {
2051  return AT_CMS_ERROR;
2052  } else if (at_match_prefix(buf, "AT+VGM=")) {
2053  return AT_VGM;
2054  } else if (at_match_prefix(buf, "AT+VGS=")) {
2055  return AT_VGS;
2056  } else if (at_match_prefix(buf, "+CUSD:")) {
2057  return AT_CUSD;
2058  } else if (at_match_prefix(buf, "BUSY")) {
2059  return AT_BUSY;
2060  } else if (at_match_prefix(buf, "NO DIALTONE")) {
2061  return AT_NO_DIALTONE;
2062  } else if (at_match_prefix(buf, "NO CARRIER")) {
2063  return AT_NO_CARRIER;
2064  } else if (at_match_prefix(buf, "*ECAV:")) {
2065  return AT_ECAM;
2066  } else {
2067  return AT_UNKNOWN;
2068  }
2069 }
2070 
2071 /*!
2072  * \brief Get the string representation of the given AT message.
2073  * \param msg the message to process
2074  * \return a string describing the given message
2075  */
2076 static inline const char *at_msg2str(at_message_t msg)
2077 {
2078  switch (msg) {
2079  /* errors */
2080  case AT_PARSE_ERROR:
2081  return "PARSE ERROR";
2082  case AT_READ_ERROR:
2083  return "READ ERROR";
2084  default:
2085  case AT_UNKNOWN:
2086  return "UNKNOWN";
2087  /* at responses */
2088  case AT_OK:
2089  return "OK";
2090  case AT_ERROR:
2091  return "ERROR";
2092  case AT_RING:
2093  return "RING";
2094  case AT_BRSF:
2095  return "AT+BRSF";
2096  case AT_CIND:
2097  return "AT+CIND";
2098  case AT_CIEV:
2099  return "AT+CIEV";
2100  case AT_CLIP:
2101  return "AT+CLIP";
2102  case AT_CMTI:
2103  return "AT+CMTI";
2104  case AT_CMGR:
2105  return "AT+CMGR";
2106  case AT_SMS_PROMPT:
2107  return "SMS PROMPT";
2108  case AT_CMS_ERROR:
2109  return "+CMS ERROR";
2110  case AT_BUSY:
2111  return "BUSY";
2112  case AT_NO_DIALTONE:
2113  return "NO DIALTONE";
2114  case AT_NO_CARRIER:
2115  return "NO CARRIER";
2116  /* at commands */
2117  case AT_A:
2118  return "ATA";
2119  case AT_D:
2120  return "ATD";
2121  case AT_CHUP:
2122  return "AT+CHUP";
2123  case AT_CKPD:
2124  return "AT+CKPD";
2125  case AT_CMGS:
2126  return "AT+CMGS";
2127  case AT_VGM:
2128  return "AT+VGM";
2129  case AT_VGS:
2130  return "AT+VGS";
2131  case AT_VTS:
2132  return "AT+VTS";
2133  case AT_CMGF:
2134  return "AT+CMGF";
2135  case AT_CNMI:
2136  return "AT+CNMI";
2137  case AT_CMER:
2138  return "AT+CMER";
2139  case AT_CIND_TEST:
2140  return "AT+CIND=?";
2141  case AT_CUSD:
2142  return "AT+CUSD";
2143  case AT_ECAM:
2144  return "AT*ECAM";
2145  }
2146 }
2147 
2148 
2149 /*
2150  * bluetooth handsfree profile helpers
2151  */
2152 
2153  /*!
2154  * \brief Parse a ECAV event.
2155  * \param hfp an hfp_pvt struct
2156  * \param buf the buffer to parse (null terminated)
2157  * \return -1 on error (parse error) or a ECAM value on success
2158  *
2159  * Example string: *ECAV: <ccid>,<ccstatus>,<calltype>[,<processid>]
2160  * [,exitcause][,<number>,<type>]
2161  *
2162  * Example indicating busy: *ECAV: 1,7,1
2163  */
2164 static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
2165 {
2166  int ccid = 0;
2167  int ccstatus = 0;
2168  int calltype = 0;
2169 
2170  if (!sscanf(buf, "*ECAV: %2d,%2d,%2d", &ccid, &ccstatus, &calltype)) {
2171  ast_debug(1, "[%s] error parsing ECAV event '%s'\n", hfp->owner->id, buf);
2172  return -1;
2173  }
2174 
2175  return ccstatus;
2176 }
2177 
2178 /*!
2179  * \brief Enable Sony Erricson extensions / indications.
2180  * \param hfp an hfp_pvt struct
2181  */
2182 static int hfp_send_ecam(struct hfp_pvt *hfp)
2183 {
2184  return rfcomm_write(hfp->rsock, "AT*ECAM=1\r");
2185 }
2186 
2187 /*!
2188  * \brief Parse a CIEV event.
2189  * \param hfp an hfp_pvt struct
2190  * \param buf the buffer to parse (null terminated)
2191  * \param value a pointer to an int to store the event value in (can be NULL)
2192  * \return 0 on error (parse error, or unknown event) or a HFP_CIND_* value on
2193  * success
2194  */
2195 static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value)
2196 {
2197  int i, v;
2198  if (!value)
2199  value = &v;
2200 
2201  if (!sscanf(buf, "+CIEV: %d,%d", &i, value)) {
2202  ast_debug(2, "[%s] error parsing CIEV event '%s'\n", hfp->owner->id, buf);
2203  return HFP_CIND_NONE;
2204  }
2205 
2206  if (i >= ARRAY_LEN(hfp->cind_state)) {
2207  ast_debug(2, "[%s] CIEV event index too high (%s)\n", hfp->owner->id, buf);
2208  return HFP_CIND_NONE;
2209  }
2210 
2211  hfp->cind_state[i] = *value;
2212  return hfp->cind_index[i];
2213 }
2214 
2215 /*!
2216  * \brief Parse a CLIP event.
2217  * \param hfp an hfp_pvt struct
2218  * \param buf the buffer to parse (null terminated)
2219  * \note buf will be modified when the CID string is parsed
2220  * \return a cidinfo structure pointing to the cnam and cnum
2221  * data in buf. On parse errors, either or both pointers
2222  * will point to null strings
2223  */
2224 static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf)
2225 {
2226  int i;
2227  int tokens[6];
2228  char *cnamtmp;
2229  char delim = ' '; /* First token terminates with space */
2230  int invalid = 0; /* Number of invalid chars in cnam */
2231  struct cidinfo cidinfo = { NULL, NULL };
2232 
2233  /* parse clip info in the following format:
2234  * +CLIP: "123456789",128,...
2235  */
2236  ast_debug(3, "[%s] hfp_parse_clip is processing \"%s\"\n", hfp->owner->id, buf);
2237  tokens[0] = 0; /* First token starts in position 0 */
2238  for (i = 1; i < ARRAY_LEN(tokens); i++) {
2239  tokens[i] = parse_next_token(buf, tokens[i - 1], delim);
2240  delim = ','; /* Subsequent tokens terminate with comma */
2241  }
2242  ast_debug(3, "[%s] hfp_parse_clip found tokens: 0=%s, 1=%s, 2=%s, 3=%s, 4=%s, 5=%s\n",
2243  hfp->owner->id, &buf[tokens[0]], &buf[tokens[1]], &buf[tokens[2]],
2244  &buf[tokens[3]], &buf[tokens[4]], &buf[tokens[5]]);
2245 
2246  /* Clean up cnum, and make sure it is legitimate since it is untrusted. */
2247  cidinfo.cnum = ast_strip_quoted(&buf[tokens[1]], "\"", "\"");
2248  if (!ast_isphonenumber(cidinfo.cnum)) {
2249  ast_debug(1, "[%s] hfp_parse_clip invalid cidinfo.cnum data \"%s\" - deleting\n",
2250  hfp->owner->id, cidinfo.cnum);
2251  cidinfo.cnum = "";
2252  }
2253 
2254  /*
2255  * Some docs say tokens 2 and 3 including the commas are optional.
2256  * If absent, that would move CNAM back to token 3.
2257  */
2258  cidinfo.cnam = &buf[tokens[5]]; /* Assume it's in token 5 */
2259  if (buf[tokens[5]] == '\0' && buf[tokens[4]] == '\0') {
2260  /* Tokens 4 and 5 are empty. See if token 3 looks like CNAM (starts with ") */
2261  i = tokens[3];
2262  while (buf[i] == ' ') { /* Find the first non-blank */
2263  i++;
2264  }
2265  if (buf[i] == '"') {
2266  /* Starts with quote. Use this for CNAM. */
2267  cidinfo.cnam = &buf[i];
2268  }
2269  }
2270 
2271  /* Clean up CNAM. */
2272  cidinfo.cnam = ast_strip_quoted(cidinfo.cnam, "\"", "\"");
2273  for (cnamtmp = cidinfo.cnam; *cnamtmp != '\0'; cnamtmp++) {
2274  if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789-,abcdefghijklmnopqrstuvwxyz_", *cnamtmp)) {
2275  *cnamtmp = '_'; /* Invalid. Replace with underscore. */
2276  invalid++;
2277  }
2278  }
2279  if (invalid) {
2280  ast_debug(2, "[%s] hfp_parse_clip replaced %d invalid byte(s) in cnam data\n",
2281  hfp->owner->id, invalid);
2282  }
2283  ast_debug(2, "[%s] hfp_parse_clip returns cnum=%s and cnam=%s\n",
2284  hfp->owner->id, cidinfo.cnum, cidinfo.cnam);
2285 
2286  return cidinfo;
2287 }
2288 
2289 /*!
2290  * \brief Terminate current token and return an index to start of the next token.
2291  * \param string the null-terminated string being parsed (will be altered!)
2292  * \param start where the current token starts
2293  * \param delim the token termination delimiter. \0 is also considered a terminator.
2294  * \return index of the next token. May be the same as this token if the string is
2295  * exhausted.
2296  */
2297 static int parse_next_token(char string[], const int start, const char delim)
2298 {
2299  int index;
2300  int quoting = 0;
2301 
2302  for (index = start; string[index] != 0; index++) {
2303  if ((string[index] == delim) && !quoting ) {
2304  /* Found the delimiter, outside of quotes. This is the end of the token. */
2305  string[index] = '\0'; /* Terminate this token. */
2306  index++; /* Point the index to the start of the next token. */
2307  break; /* We're done. */
2308  } else if (string[index] == '"' && !quoting) {
2309  /* Found a beginning quote mark. Remember it. */
2310  quoting = 1;
2311  } else if (string[index] == '"' ) {
2312  /* Found the end quote mark. */
2313  quoting = 0;
2314  }
2315  }
2316  return index;
2317 }
2318 
2319 /*!
2320  * \brief Parse a CMTI notification.
2321  * \param hfp an hfp_pvt struct
2322  * \param buf the buffer to parse (null terminated)
2323  * \note buf will be modified when the CMTI message is parsed
2324  * \return -1 on error (parse error) or the index of the new sms message
2325  */
2326 static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf)
2327 {
2328  int index = -1;
2329 
2330  /* parse cmti info in the following format:
2331  * +CMTI: <mem>,<index>
2332  */
2333  if (!sscanf(buf, "+CMTI: %*[^,],%d", &index)) {
2334  ast_debug(2, "[%s] error parsing CMTI event '%s'\n", hfp->owner->id, buf);
2335  return -1;
2336  }
2337 
2338  return index;
2339 }
2340 
2341 /*!
2342  * \brief Parse a CMGR message.
2343  * \param hfp an hfp_pvt struct
2344  * \param buf the buffer to parse (null terminated)
2345  * \param from_number a pointer to a char pointer which will store the from
2346  * number
2347  * \param text a pointer to a char pointer which will store the message text
2348  * \note buf will be modified when the CMGR message is parsed
2349  * \retval -1 parse error
2350  * \retval 0 success
2351  */
2352 static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text)
2353 {
2354  int i, state;
2355  size_t s;
2356 
2357  /* parse cmgr info in the following format:
2358  * +CMGR: <msg status>,"+123456789",...\r\n
2359  * <message text>
2360  */
2361  state = 0;
2362  s = strlen(buf);
2363  for (i = 0; i < s && state != 6; i++) {
2364  switch (state) {
2365  case 0: /* search for start of the number section (,) */
2366  if (buf[i] == ',') {
2367  state++;
2368  }
2369  break;
2370  case 1: /* find the opening quote (") */
2371  if (buf[i] == '"') {
2372  state++;
2373  }
2374  break;
2375  case 2: /* mark the start of the number */
2376  if (from_number) {
2377  *from_number = &buf[i];
2378  state++;
2379  }
2380  /* fall through */
2381  case 3: /* search for the end of the number (") */
2382  if (buf[i] == '"') {
2383  buf[i] = '\0';
2384  state++;
2385  }
2386  break;
2387  case 4: /* search for the start of the message text (\n) */
2388  if (buf[i] == '\n') {
2389  state++;
2390  }
2391  break;
2392  case 5: /* mark the start of the message text */
2393  if (text) {
2394  *text = &buf[i];
2395  state++;
2396  }
2397  break;
2398  }
2399  }
2400 
2401  if (state != 6) {
2402  return -1;
2403  }
2404 
2405  return 0;
2406 }
2407 
2408 /*!
2409  * \brief Parse a CUSD answer.
2410  * \param hfp an hfp_pvt struct
2411  * \param buf the buffer to parse (null terminated)
2412  * \note buf will be modified when the CUSD string is parsed
2413  * \return NULL on error (parse error) or a pointer to the cusd message
2414  * information in buf
2415  */
2416 static char *hfp_parse_cusd(struct hfp_pvt *hfp, char *buf)
2417 {
2418  int i, message_start, message_end;
2419  char *cusd;
2420  size_t s;
2421 
2422  /* parse cusd message in the following format:
2423  * +CUSD: 0,"100,00 EURO, valid till 01.01.2010, you are using tariff "Mega Tariff". More informations *111#."
2424  */
2425  message_start = 0;
2426  message_end = 0;
2427  s = strlen(buf);
2428 
2429  /* Find the start of the message (") */
2430  for (i = 0; i < s; i++) {
2431  if (buf[i] == '"') {
2432  message_start = i + 1;
2433  break;
2434  }
2435  }
2436 
2437  if (message_start == 0 || message_start >= s) {
2438  return NULL;
2439  }
2440 
2441  /* Find the end of the message (") */
2442  for (i = s; i > 0; i--) {
2443  if (buf[i] == '"') {
2444  message_end = i;
2445  break;
2446  }
2447  }
2448 
2449  if (message_end == 0) {
2450  return NULL;
2451  }
2452 
2453  if (message_start >= message_end) {
2454  return NULL;
2455  }
2456 
2457  cusd = &buf[message_start];
2458  buf[message_end] = '\0';
2459 
2460  return cusd;
2461 }
2462 
2463 /*!
2464  * \brief Convert a hfp_hf struct to a BRSF int.
2465  * \param hf an hfp_hf brsf object
2466  * \return an integer representing the given brsf struct
2467  */
2468 static int hfp_brsf2int(struct hfp_hf *hf)
2469 {
2470  int brsf = 0;
2471 
2472  brsf |= hf->ecnr ? HFP_HF_ECNR : 0;
2473  brsf |= hf->cw ? HFP_HF_CW : 0;
2474  brsf |= hf->cid ? HFP_HF_CID : 0;
2475  brsf |= hf->voice ? HFP_HF_VOICE : 0;
2476  brsf |= hf->volume ? HFP_HF_VOLUME : 0;
2477  brsf |= hf->status ? HFP_HF_STATUS : 0;
2478  brsf |= hf->control ? HFP_HF_CONTROL : 0;
2479 
2480  return brsf;
2481 }
2482 
2483 /*!
2484  * \brief Convert a BRSF int to an hfp_ag struct.
2485  * \param brsf a brsf integer
2486  * \param ag a AG (hfp_ag) brsf object
2487  * \return a pointer to the given hfp_ag object populated with the values from
2488  * the given brsf integer
2489  */
2490 static struct hfp_ag *hfp_int2brsf(int brsf, struct hfp_ag *ag)
2491 {
2492  ag->cw = brsf & HFP_AG_CW ? 1 : 0;
2493  ag->ecnr = brsf & HFP_AG_ECNR ? 1 : 0;
2494  ag->voice = brsf & HFP_AG_VOICE ? 1 : 0;
2495  ag->ring = brsf & HFP_AG_RING ? 1 : 0;
2496  ag->tag = brsf & HFP_AG_TAG ? 1 : 0;
2497  ag->reject = brsf & HFP_AG_REJECT ? 1 : 0;
2498  ag->status = brsf & HFP_AG_STATUS ? 1 : 0;
2499  ag->control = brsf & HFP_AG_CONTROL ? 1 : 0;
2500  ag->errors = brsf & HFP_AG_ERRORS ? 1 : 0;
2501 
2502  return ag;
2503 }
2504 
2505 
2506 /*!
2507  * \brief Send a BRSF request.
2508  * \param hfp an hfp_pvt struct
2509  * \param brsf an hfp_hf brsf struct
2510  *
2511  * \retval 0 on success
2512  * \retval -1 on error
2513  */
2514 static int hfp_send_brsf(struct hfp_pvt *hfp, struct hfp_hf *brsf)
2515 {
2516  char cmd[32];
2517  snprintf(cmd, sizeof(cmd), "AT+BRSF=%d\r", hfp_brsf2int(brsf));
2518  return rfcomm_write(hfp->rsock, cmd);
2519 }
2520 
2521 /*!
2522  * \brief Send the CIND read command.
2523  * \param hfp an hfp_pvt struct
2524  */
2525 static int hfp_send_cind(struct hfp_pvt *hfp)
2526 {
2527  return rfcomm_write(hfp->rsock, "AT+CIND?\r");
2528 }
2529 
2530 /*!
2531  * \brief Send the CIND test command.
2532  * \param hfp an hfp_pvt struct
2533  */
2534 static int hfp_send_cind_test(struct hfp_pvt *hfp)
2535 {
2536  return rfcomm_write(hfp->rsock, "AT+CIND=?\r");
2537 }
2538 
2539 /*!
2540  * \brief Enable or disable indicator events reporting.
2541  * \param hfp an hfp_pvt struct
2542  * \param status enable or disable events reporting (should be 1 or 0)
2543  */
2544 static int hfp_send_cmer(struct hfp_pvt *hfp, int status)
2545 {
2546  char cmd[32];
2547  snprintf(cmd, sizeof(cmd), "AT+CMER=3,0,0,%d\r", status ? 1 : 0);
2548  return rfcomm_write(hfp->rsock, cmd);
2549 }
2550 
2551 /*!
2552  * \brief Send the current speaker gain level.
2553  * \param hfp an hfp_pvt struct
2554  * \param value the value to send (must be between 0 and 15)
2555  */
2556 static int hfp_send_vgs(struct hfp_pvt *hfp, int value)
2557 {
2558  char cmd[32];
2559  snprintf(cmd, sizeof(cmd), "AT+VGS=%d\r", value);
2560  return rfcomm_write(hfp->rsock, cmd);
2561 }
2562 
2563 #if 0
2564 /*!
2565  * \brief Send the current microphone gain level.
2566  * \param hfp an hfp_pvt struct
2567  * \param value the value to send (must be between 0 and 15)
2568  */
2569 static int hfp_send_vgm(struct hfp_pvt *hfp, int value)
2570 {
2571  char cmd[32];
2572  snprintf(cmd, sizeof(cmd), "AT+VGM=%d\r", value);
2573  return rfcomm_write(hfp->rsock, cmd);
2574 }
2575 #endif
2576 
2577 /*!
2578  * \brief Enable or disable calling line identification.
2579  * \param hfp an hfp_pvt struct
2580  * \param status enable or disable calling line identification (should be 1 or
2581  * 0)
2582  */
2583 static int hfp_send_clip(struct hfp_pvt *hfp, int status)
2584 {
2585  char cmd[32];
2586  snprintf(cmd, sizeof(cmd), "AT+CLIP=%d\r", status ? 1 : 0);
2587  return rfcomm_write(hfp->rsock, cmd);
2588 }
2589 
2590 /*!
2591  * \brief Send a DTMF command.
2592  * \param hfp an hfp_pvt struct
2593  * \param digit the dtmf digit to send
2594  * \return the result of rfcomm_write() or -1 on an invalid digit being sent
2595  */
2596 static int hfp_send_dtmf(struct hfp_pvt *hfp, char digit)
2597 {
2598  char cmd[10];
2599 
2600  switch(digit) {
2601  case '0':
2602  case '1':
2603  case '2':
2604  case '3':
2605  case '4':
2606  case '5':
2607  case '6':
2608  case '7':
2609  case '8':
2610  case '9':
2611  case '*':
2612  case '#':
2613  snprintf(cmd, sizeof(cmd), "AT+VTS=%c\r", digit);
2614  return rfcomm_write(hfp->rsock, cmd);
2615  default:
2616  return -1;
2617  }
2618 }
2619 
2620 /*!
2621  * \brief Set the SMS mode.
2622  * \param hfp an hfp_pvt struct
2623  * \param mode the sms mode (0 = PDU, 1 = Text)
2624  */
2625 static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode)
2626 {
2627  char cmd[32];
2628  snprintf(cmd, sizeof(cmd), "AT+CMGF=%d\r", mode);
2629  return rfcomm_write(hfp->rsock, cmd);
2630 }
2631 
2632 /*!
2633  * \brief Setup SMS new message indication.
2634  * \param hfp an hfp_pvt struct
2635  */
2636 static int hfp_send_cnmi(struct hfp_pvt *hfp)
2637 {
2638  return rfcomm_write(hfp->rsock, "AT+CNMI=2,1,0,0,0\r");
2639 }
2640 
2641 /*!
2642  * \brief Read an SMS message.
2643  * \param hfp an hfp_pvt struct
2644  * \param index the location of the requested message
2645  */
2646 static int hfp_send_cmgr(struct hfp_pvt *hfp, int index)
2647 {
2648  char cmd[32];
2649  snprintf(cmd, sizeof(cmd), "AT+CMGR=%d\r", index);
2650  return rfcomm_write(hfp->rsock, cmd);
2651 }
2652 
2653 /*!
2654  * \brief Start sending an SMS message.
2655  * \param hfp an hfp_pvt struct
2656  * \param number the destination of the message
2657  */
2658 static int hfp_send_cmgs(struct hfp_pvt *hfp, const char *number)
2659 {
2660  char cmd[64];
2661  snprintf(cmd, sizeof(cmd), "AT+CMGS=\"%s\"\r", number);
2662  return rfcomm_write(hfp->rsock, cmd);
2663 }
2664 
2665 /*!
2666  * \brief Send the text of an SMS message.
2667  * \param hfp an hfp_pvt struct
2668  * \param message the text of the message
2669  */
2670 static int hfp_send_sms_text(struct hfp_pvt *hfp, const char *message)
2671 {
2672  char cmd[162];
2673  snprintf(cmd, sizeof(cmd), "%.160s\x1a", message);
2674  return rfcomm_write(hfp->rsock, cmd);
2675 }
2676 
2677 /*!
2678  * \brief Send AT+CHUP.
2679  * \param hfp an hfp_pvt struct
2680  */
2681 static int hfp_send_chup(struct hfp_pvt *hfp)
2682 {
2683  return rfcomm_write(hfp->rsock, "AT+CHUP\r");
2684 }
2685 
2686 /*!
2687  * \brief Send ATD.
2688  * \param hfp an hfp_pvt struct
2689  * \param number the number to send
2690  */
2691 static int hfp_send_atd(struct hfp_pvt *hfp, const char *number)
2692 {
2693  char cmd[64];
2694  snprintf(cmd, sizeof(cmd), "ATD%s;\r", number);
2695  return rfcomm_write(hfp->rsock, cmd);
2696 }
2697 
2698 /*!
2699  * \brief Send ATA.
2700  * \param hfp an hfp_pvt struct
2701  */
2702 static int hfp_send_ata(struct hfp_pvt *hfp)
2703 {
2704  return rfcomm_write(hfp->rsock, "ATA\r");
2705 }
2706 
2707 /*!
2708  * \brief Send CUSD.
2709  * \param hfp an hfp_pvt struct
2710  * \param code the CUSD code to send
2711  */
2712 static int hfp_send_cusd(struct hfp_pvt *hfp, const char *code)
2713 {
2714  char cmd[128];
2715  snprintf(cmd, sizeof(cmd), "AT+CUSD=1,\"%s\",15\r", code);
2716  return rfcomm_write(hfp->rsock, cmd);
2717 }
2718 
2719 /*!
2720  * \brief Parse BRSF data.
2721  * \param hfp an hfp_pvt struct
2722  * \param buf the buffer to parse (null terminated)
2723  */
2724 static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf)
2725 {
2726  int brsf;
2727 
2728  if (!sscanf(buf, "+BRSF:%d", &brsf))
2729  return -1;
2730 
2731  hfp_int2brsf(brsf, &hfp->brsf);
2732 
2733  return 0;
2734 }
2735 
2736 /*!
2737  * \brief Parse and store the given indicator.
2738  * \param hfp an hfp_pvt struct
2739  * \param group the indicator group
2740  * \param indicator the indicator to parse
2741  */
2742 static int hfp_parse_cind_indicator(struct hfp_pvt *hfp, int group, char *indicator)
2743 {
2744  int value;
2745 
2746  /* store the current indicator */
2747  if (group >= ARRAY_LEN(hfp->cind_state)) {
2748  ast_debug(1, "ignoring CIND state '%s' for group %d, we only support up to %d indicators\n", indicator, group, (int) sizeof(hfp->cind_state));
2749  return -1;
2750  }
2751 
2752  if (!sscanf(indicator, "%d", &value)) {
2753  ast_debug(1, "error parsing CIND state '%s' for group %d\n", indicator, group);
2754  return -1;
2755  }
2756 
2757  hfp->cind_state[group] = value;
2758  return 0;
2759 }
2760 
2761 /*!
2762  * \brief Read the result of the AT+CIND? command.
2763  * \param hfp an hfp_pvt struct
2764  * \param buf the buffer to parse (null terminated)
2765  * \note hfp_send_cind_test() and hfp_parse_cind_test() should be called at
2766  * least once before this function is called.
2767  */
2768 static int hfp_parse_cind(struct hfp_pvt *hfp, char *buf)
2769 {
2770  int i, state, group;
2771  size_t s;
2772  char *indicator = NULL;
2773 
2774  /* parse current state of all of our indicators. The list is in the
2775  * following format:
2776  * +CIND: 1,0,2,0,0,0,0
2777  */
2778  group = 0;
2779  state = 0;
2780  s = strlen(buf);
2781  for (i = 0; i < s; i++) {
2782  switch (state) {
2783  case 0: /* search for start of the status indicators (a space) */
2784  if (buf[i] == ' ') {
2785  group++;
2786  state++;
2787  }
2788  break;
2789  case 1: /* mark this indicator */
2790  indicator = &buf[i];
2791  state++;
2792  break;
2793  case 2: /* search for the start of the next indicator (a comma) */
2794  if (buf[i] == ',') {
2795  buf[i] = '\0';
2796 
2797  hfp_parse_cind_indicator(hfp, group, indicator);
2798 
2799  group++;
2800  state = 1;
2801  }
2802  break;
2803  }
2804  }
2805 
2806  /* store the last indicator */
2807  if (state == 2)
2808  hfp_parse_cind_indicator(hfp, group, indicator);
2809 
2810  return 0;
2811 }
2812 
2813 /*!
2814  * \brief Parse the result of the AT+CIND=? command.
2815  * \param hfp an hfp_pvt struct
2816  * \param buf the buffer to parse (null terminated)
2817  */
2818 static int hfp_parse_cind_test(struct hfp_pvt *hfp, char *buf)
2819 {
2820  int i, state, group;
2821  size_t s;
2822  char *indicator = NULL;
2823 
2824  hfp->nocallsetup = 1;
2825 
2826  /* parse the indications list. It is in the follwing format:
2827  * +CIND: ("ind1",(0-1)),("ind2",(0-5))
2828  */
2829  group = 0;
2830  state = 0;
2831  s = strlen(buf);
2832  for (i = 0; i < s; i++) {
2833  switch (state) {
2834  case 0: /* search for start of indicator block */
2835  if (buf[i] == '(') {
2836  group++;
2837  state++;
2838  }
2839  break;
2840  case 1: /* search for '"' in indicator block */
2841  if (buf[i] == '"') {
2842  state++;
2843  }
2844  break;
2845  case 2: /* mark the start of the indicator name */
2846  indicator = &buf[i];
2847  state++;
2848  break;
2849  case 3: /* look for the end of the indicator name */
2850  if (buf[i] == '"') {
2851  buf[i] = '\0';
2852  state++;
2853  }
2854  break;
2855  case 4: /* find the start of the value range */
2856  if (buf[i] == '(') {
2857  state++;
2858  }
2859  break;
2860  case 5: /* mark the start of the value range */
2861  state++;
2862  break;
2863  case 6: /* find the end of the value range */
2864  if (buf[i] == ')') {
2865  buf[i] = '\0';
2866  state++;
2867  }
2868  break;
2869  case 7: /* process the values we found */
2870  if (group < sizeof(hfp->cind_index)) {
2871  if (!strcmp(indicator, "service")) {
2872  hfp->cind_map.service = group;
2873  hfp->cind_index[group] = HFP_CIND_SERVICE;
2874  } else if (!strcmp(indicator, "call")) {
2875  hfp->cind_map.call = group;
2876  hfp->cind_index[group] = HFP_CIND_CALL;
2877  } else if (!strcmp(indicator, "callsetup")) {
2878  hfp->nocallsetup = 0;
2879  hfp->cind_map.callsetup = group;
2880  hfp->cind_index[group] = HFP_CIND_CALLSETUP;
2881  } else if (!strcmp(indicator, "call_setup")) { /* non standard call setup identifier */
2882  hfp->nocallsetup = 0;
2883  hfp->cind_map.callsetup = group;
2884  hfp->cind_index[group] = HFP_CIND_CALLSETUP;
2885  } else if (!strcmp(indicator, "callheld")) {
2886  hfp->cind_map.callheld = group;
2887  hfp->cind_index[group] = HFP_CIND_CALLHELD;
2888  } else if (!strcmp(indicator, "signal")) {
2889  hfp->cind_map.signal = group;
2890  hfp->cind_index[group] = HFP_CIND_SIGNAL;
2891  } else if (!strcmp(indicator, "roam")) {
2892  hfp->cind_map.roam = group;
2893  hfp->cind_index[group] = HFP_CIND_ROAM;
2894  } else if (!strcmp(indicator, "battchg")) {
2895  hfp->cind_map.battchg = group;
2896  hfp->cind_index[group] = HFP_CIND_BATTCHG;
2897  } else {
2898  hfp->cind_index[group] = HFP_CIND_UNKNOWN;
2899  ast_debug(2, "ignoring unknown CIND indicator '%s'\n", indicator);
2900  }
2901  } else {
2902  ast_debug(1, "can't store indicator %d (%s), we only support up to %d indicators", group, indicator, (int) sizeof(hfp->cind_index));
2903  }
2904 
2905  state = 0;
2906  break;
2907  }
2908  }
2909 
2910  hfp->owner->no_callsetup = hfp->nocallsetup;
2911 
2912  return 0;
2913 }
2914 
2915 
2916 /*
2917  * Bluetooth Headset Profile helpers
2918  */
2919 
2920 /*!
2921  * \brief Send an OK AT response.
2922  * \param rsock the rfcomm socket to use
2923  */
2924 static int hsp_send_ok(int rsock)
2925 {
2926  return rfcomm_write(rsock, "\r\nOK\r\n");
2927 }
2928 
2929 /*!
2930  * \brief Send an ERROR AT response.
2931  * \param rsock the rfcomm socket to use
2932  */
2933 static int hsp_send_error(int rsock)
2934 {
2935  return rfcomm_write(rsock, "\r\nERROR\r\n");
2936 }
2937 
2938 /*!
2939  * \brief Send a speaker gain unsolicited AT response
2940  * \param rsock the rfcomm socket to use
2941  * \param gain the speaker gain value
2942  */
2943 static int hsp_send_vgs(int rsock, int gain)
2944 {
2945  char cmd[32];
2946  snprintf(cmd, sizeof(cmd), "\r\n+VGS=%d\r\n", gain);
2947  return rfcomm_write(rsock, cmd);
2948 }
2949 
2950 /*!
2951  * \brief Send a microphone gain unsolicited AT response
2952  * \param rsock the rfcomm socket to use
2953  * \param gain the microphone gain value
2954  */
2955 static int hsp_send_vgm(int rsock, int gain)
2956 {
2957  char cmd[32];
2958  snprintf(cmd, sizeof(cmd), "\r\n+VGM=%d\r\n", gain);
2959  return rfcomm_write(rsock, cmd);
2960 }
2961 
2962 /*!
2963  * \brief Send a RING unsolicited AT response.
2964  * \param rsock the rfcomm socket to use
2965  */
2966 static int hsp_send_ring(int rsock)
2967 {
2968  return rfcomm_write(rsock, "\r\nRING\r\n");
2969 }
2970 
2971 /*
2972  * message queue functions
2973  */
2974 
2975 /*!
2976  * \brief Add an item to the back of the queue.
2977  * \param pvt a mbl_pvt structure
2978  * \param expect the msg we expect to receive
2979  * \param response_to the message that was sent to generate the expected
2980  * response
2981  */
2982 static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
2983 {
2984  struct msg_queue_entry *msg;
2985  if (!(msg = ast_calloc(1, sizeof(*msg)))) {
2986  return -1;
2987  }
2988  msg->expected = expect;
2989  msg->response_to = response_to;
2990 
2991  AST_LIST_INSERT_TAIL(&pvt->msg_queue, msg, entry);
2992  return 0;
2993 }
2994 
2995 /*!
2996  * \brief Add an item to the back of the queue with data.
2997  * \param pvt a mbl_pvt structure
2998  * \param expect the msg we expect to receive
2999  * \param response_to the message that was sent to generate the expected
3000  * response
3001  * \param data data associated with this message, it will be freed when the
3002  * message is freed
3003  */
3004 static int msg_queue_push_data(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to, void *data)
3005 {
3006  struct msg_queue_entry *msg;
3007  if (!(msg = ast_calloc(1, sizeof(*msg)))) {
3008  return -1;
3009  }
3010  msg->expected = expect;
3011  msg->response_to = response_to;
3012  msg->data = data;
3013 
3014  AST_LIST_INSERT_TAIL(&pvt->msg_queue, msg, entry);
3015  return 0;
3016 }
3017 
3018 /*!
3019  * \brief Remove an item from the front of the queue.
3020  * \param pvt a mbl_pvt structure
3021  * \return a pointer to the removed item
3022  */
3023 static struct msg_queue_entry *msg_queue_pop(struct mbl_pvt *pvt)
3024 {
3025  return AST_LIST_REMOVE_HEAD(&pvt->msg_queue, entry);
3026 }
3027 
3028 /*!
3029  * \brief Remove an item from the front of the queue, and free it.
3030  * \param pvt a mbl_pvt structure
3031  */
3032 static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
3033 {
3034  struct msg_queue_entry *msg;
3035  if ((msg = msg_queue_pop(pvt))) {
3036  if (msg->data)
3037  ast_free(msg->data);
3038  ast_free(msg);
3039  }
3040 }
3041 
3042 /*!
3043  * \brief Remove all itmes from the queue and free them.
3044  * \param pvt a mbl_pvt structure
3045  */
3046 static void msg_queue_flush(struct mbl_pvt *pvt)
3047 {
3048  struct msg_queue_entry *msg;
3049  while ((msg = msg_queue_head(pvt)))
3051 }
3052 
3053 /*!
3054  * \brief Get the head of a queue.
3055  * \param pvt a mbl_pvt structure
3056  * \return a pointer to the head of the given msg queue
3057  */
3058 static struct msg_queue_entry *msg_queue_head(struct mbl_pvt *pvt)
3059 {
3060  return AST_LIST_FIRST(&pvt->msg_queue);
3061 }
3062 
3063 
3064 
3065 /*
3066 
3067  sdp helpers
3068 
3069 */
3070 
3071 static int sdp_search(char *addr, int profile)
3072 {
3073 
3074  sdp_session_t *session = 0;
3075  bdaddr_t bdaddr;
3076  uuid_t svc_uuid;
3077  uint32_t range = 0x0000ffff;
3078  sdp_list_t *response_list, *search_list, *attrid_list;
3079  int status, port;
3080  sdp_list_t *proto_list;
3081  sdp_record_t *sdprec;
3082 
3083  str2ba(addr, &bdaddr);
3084  port = 0;
3085  session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
3086  if (!session) {
3087  ast_debug(1, "sdp_connect() failed on device %s.\n", addr);
3088  return 0;
3089  }
3090 
3091  sdp_uuid32_create(&svc_uuid, profile);
3092  search_list = sdp_list_append(0, &svc_uuid);
3093  attrid_list = sdp_list_append(0, &range);
3094  response_list = 0x00;
3095  status = sdp_service_search_attr_req(session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
3096  if (status == 0) {
3097  if (response_list) {
3098  sdprec = (sdp_record_t *) response_list->data;
3099  proto_list = 0x00;
3100  if (sdp_get_access_protos(sdprec, &proto_list) == 0) {
3101  port = sdp_get_proto_port(proto_list, RFCOMM_UUID);
3102  sdp_list_free(proto_list, 0);
3103  }
3104  sdp_record_free(sdprec);
3105  sdp_list_free(response_list, 0);
3106  } else
3107  ast_debug(1, "No responses returned for device %s.\n", addr);
3108  } else
3109  ast_debug(1, "sdp_service_search_attr_req() failed on device %s.\n", addr);
3110 
3111  sdp_list_free(search_list, 0);
3112  sdp_list_free(attrid_list, 0);
3113  sdp_close(session);
3114 
3115  return port;
3116 
3117 }
3118 
3119 static sdp_session_t *sdp_register(void)
3120 {
3121  uint32_t service_uuid_int[] = {0, 0, 0, GENERIC_AUDIO_SVCLASS_ID};
3122  uint8_t rfcomm_channel = 1;
3123  const char *service_name = "Asterisk PABX";
3124  const char *service_dsc = "Asterisk PABX";
3125  const char *service_prov = "Asterisk";
3126 
3127  uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class1_uuid, svc_class2_uuid;
3128  sdp_list_t *l2cap_list = 0, *rfcomm_list = 0, *root_list = 0, *proto_list = 0, *access_proto_list = 0, *svc_uuid_list = 0;
3129  sdp_data_t *channel = 0;
3130 
3131  sdp_session_t *session = 0;
3132 
3133  sdp_record_t *record = sdp_record_alloc();
3134 
3135  sdp_uuid128_create(&svc_uuid, &service_uuid_int);
3136  sdp_set_service_id(record, svc_uuid);
3137 
3138  sdp_uuid32_create(&svc_class1_uuid, GENERIC_AUDIO_SVCLASS_ID);
3139  sdp_uuid32_create(&svc_class2_uuid, HEADSET_PROFILE_ID);
3140 
3141  svc_uuid_list = sdp_list_append(0, &svc_class1_uuid);
3142  svc_uuid_list = sdp_list_append(svc_uuid_list, &svc_class2_uuid);
3143  sdp_set_service_classes(record, svc_uuid_list);
3144 
3145  sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3146  root_list = sdp_list_append(0, &root_uuid);
3147  sdp_set_browse_groups( record, root_list );
3148 
3149  sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3150  l2cap_list = sdp_list_append(0, &l2cap_uuid);
3151  proto_list = sdp_list_append(0, l2cap_list);
3152 
3153  sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3154  channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
3155  rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
3156  sdp_list_append(rfcomm_list, channel);
3157  sdp_list_append(proto_list, rfcomm_list);
3158 
3159  access_proto_list = sdp_list_append(0, proto_list);
3160  sdp_set_access_protos(record, access_proto_list);
3161 
3162  sdp_set_info_attr(record, service_name, service_prov, service_dsc);
3163 
3164  if (!(session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY)))
3165  ast_log(LOG_WARNING, "Failed to connect sdp and create session.\n");
3166  else {
3167  if (sdp_record_register(session, record, 0) < 0) {
3168  ast_log(LOG_WARNING, "Failed to sdp_record_register error: %d\n", errno);
3169  return NULL;
3170  }
3171  }
3172 
3173  sdp_data_free(channel);
3174  sdp_list_free(rfcomm_list, 0);
3175  sdp_list_free(root_list, 0);
3176  sdp_list_free(access_proto_list, 0);
3177  sdp_list_free(svc_uuid_list, 0);
3178 
3179  return session;
3180 
3181 }
3182 
3183 /*
3184 
3185  Thread routines
3186 
3187 */
3188 
3189 /*!
3190  * \brief Handle the BRSF response.
3191  * \param pvt a mbl_pvt structure
3192  * \param buf a null terminated buffer containing an AT message
3193  * \retval 0 success
3194  * \retval -1 error
3195  */
3196 static int handle_response_brsf(struct mbl_pvt *pvt, char *buf)
3197 {
3198  struct msg_queue_entry *entry;
3199  if ((entry = msg_queue_head(pvt)) && entry->expected == AT_BRSF) {
3200  if (hfp_parse_brsf(pvt->hfp, buf)) {
3201  ast_debug(1, "[%s] error parsing BRSF\n", pvt->id);
3202  goto e_return;
3203  }
3204 
3205  if (msg_queue_push(pvt, AT_OK, AT_BRSF)) {
3206  ast_debug(1, "[%s] error handling BRSF\n", pvt->id);
3207  goto e_return;
3208  }
3209 
3211  } else if (entry) {
3212  ast_debug(1, "[%s] received unexpected AT message 'BRSF' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3213  } else {
3214  ast_debug(1, "[%s] received unexpected AT message 'BRSF'\n", pvt->id);
3215  }
3216 
3217  return 0;
3218 
3219 e_return:
3221  return -1;
3222 }
3223 
3224 /*!
3225  * \brief Handle the CIND response.
3226  * \param pvt a mbl_pvt structure
3227  * \param buf a null terminated buffer containing an AT message
3228  * \retval 0 success
3229  * \retval -1 error
3230  */
3231 static int handle_response_cind(struct mbl_pvt *pvt, char *buf)
3232 {
3233  struct msg_queue_entry *entry;
3234  if ((entry = msg_queue_head(pvt)) && entry->expected == AT_CIND) {
3235  switch (entry->response_to) {
3236  case AT_CIND_TEST:
3237  if (hfp_parse_cind_test(pvt->hfp, buf) || msg_queue_push(pvt, AT_OK, AT_CIND_TEST)) {
3238  ast_debug(1, "[%s] error performing CIND test\n", pvt->id);
3239  goto e_return;
3240  }
3241  break;
3242  case AT_CIND:
3243  if (hfp_parse_cind(pvt->hfp, buf) || msg_queue_push(pvt, AT_OK, AT_CIND)) {
3244  ast_debug(1, "[%s] error getting CIND state\n", pvt->id);
3245  goto e_return;
3246  }
3247  break;
3248  default:
3249  ast_debug(1, "[%s] error getting CIND state\n", pvt->id);
3250  goto e_return;
3251  }
3253  } else if (entry) {
3254  ast_debug(1, "[%s] received unexpected AT message 'CIND' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3255  } else {
3256  ast_debug(1, "[%s] received unexpected AT message 'CIND'\n", pvt->id);
3257  }
3258 
3259  return 0;
3260 
3261 e_return:
3263  return -1;
3264 }
3265 
3266 /*!
3267  * \brief Handle OK AT messages.
3268  * \param pvt a mbl_pvt structure
3269  * \param buf a null terminated buffer containing an AT message
3270  * \retval 0 success
3271  * \retval -1 error
3272  */
3273 static int handle_response_ok(struct mbl_pvt *pvt, char *buf)
3274 {
3275  struct msg_queue_entry *entry;
3276  if ((entry = msg_queue_head(pvt)) && entry->expected == AT_OK) {
3277  switch (entry->response_to) {
3278 
3279  /* initialization stuff */
3280  case AT_BRSF:
3281  ast_debug(1, "[%s] BSRF sent successfully\n", pvt->id);
3282 
3283  /* If this is a blackberry do CMER now, otherwise
3284  * continue with CIND as normal. */
3285  if (pvt->blackberry) {
3286  if (hfp_send_cmer(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMER)) {
3287  ast_debug(1, "[%s] error sending CMER\n", pvt->id);
3288  goto e_return;
3289  }
3290  } else {
3292  ast_debug(1, "[%s] error sending CIND test\n", pvt->id);
3293  goto e_return;
3294  }
3295  }
3296  break;
3297  case AT_CIND_TEST:
3298  ast_debug(1, "[%s] CIND test sent successfully\n", pvt->id);
3299 
3300  ast_debug(2, "[%s] call: %d\n", pvt->id, pvt->hfp->cind_map.call);
3301  ast_debug(2, "[%s] callsetup: %d\n", pvt->id, pvt->hfp->cind_map.callsetup);
3302  ast_debug(2, "[%s] service: %d\n", pvt->id, pvt->hfp->cind_map.service);
3303 
3304  if (hfp_send_cind(pvt->hfp) || msg_queue_push(pvt, AT_CIND, AT_CIND)) {
3305  ast_debug(1, "[%s] error requesting CIND state\n", pvt->id);
3306  goto e_return;
3307  }
3308  break;
3309  case AT_CIND:
3310  ast_debug(1, "[%s] CIND sent successfully\n", pvt->id);
3311 
3312  /* check if a call is active */
3313  if (pvt->hfp->cind_state[pvt->hfp->cind_map.call]) {
3314  ast_verb(3, "Bluetooth Device %s has a call in progress - delaying connection.\n", pvt->id);
3315  goto e_return;
3316  }
3317 
3318  /* If this is NOT a blackberry proceed with CMER,
3319  * otherwise send CLIP. */
3320  if (!pvt->blackberry) {
3321  if (hfp_send_cmer(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMER)) {
3322  ast_debug(1, "[%s] error sending CMER\n", pvt->id);
3323  goto e_return;
3324  }
3325  } else {
3326  if (hfp_send_clip(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CLIP)) {
3327  ast_debug(1, "[%s] error enabling calling line notification\n", pvt->id);
3328  goto e_return;
3329  }
3330  }
3331  break;
3332  case AT_CMER:
3333  ast_debug(1, "[%s] CMER sent successfully\n", pvt->id);
3334 
3335  /* If this is a blackberry proceed with the CIND test,
3336  * otherwise send CLIP. */
3337  if (pvt->blackberry) {
3339  ast_debug(1, "[%s] error sending CIND test\n", pvt->id);
3340  goto e_return;
3341  }
3342  } else {
3343  if (hfp_send_clip(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CLIP)) {
3344  ast_debug(1, "[%s] error enabling calling line notification\n", pvt->id);
3345  goto e_return;
3346  }
3347  }
3348  break;
3349  case AT_CLIP:
3350  ast_debug(1, "[%s] caling line indication enabled\n", pvt->id);
3351  if (hfp_send_ecam(pvt->hfp) || msg_queue_push(pvt, AT_OK, AT_ECAM)) {
3352  ast_debug(1, "[%s] error enabling Sony Ericsson call monitoring extensions\n", pvt->id);
3353  goto e_return;
3354  }
3355 
3356  break;
3357  case AT_ECAM:
3358  ast_debug(1, "[%s] Sony Ericsson call monitoring is active on device\n", pvt->id);
3359  if (hfp_send_vgs(pvt->hfp, 15) || msg_queue_push(pvt, AT_OK, AT_VGS)) {
3360  ast_debug(1, "[%s] error synchronizing gain settings\n", pvt->id);
3361  goto e_return;
3362  }
3363 
3364  pvt->timeout = -1;
3365  pvt->hfp->initialized = 1;
3366  ast_verb(3, "Bluetooth Device %s initialized and ready.\n", pvt->id);
3367 
3368  break;
3369  case AT_VGS:
3370  ast_debug(1, "[%s] volume level synchronization successful\n", pvt->id);
3371 
3372  /* set the SMS operating mode to text mode */
3373  if (pvt->has_sms) {
3374  if (hfp_send_cmgf(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMGF)) {
3375  ast_debug(1, "[%s] error setting CMGF\n", pvt->id);
3376  goto e_return;
3377  }
3378  }
3379  break;
3380  case AT_CMGF:
3381  ast_debug(1, "[%s] sms text mode enabled\n", pvt->id);
3382  /* turn on SMS new message indication */
3383  if (hfp_send_cnmi(pvt->hfp) || msg_queue_push(pvt, AT_OK, AT_CNMI)) {
3384  ast_debug(1, "[%s] error setting CNMI\n", pvt->id);
3385  goto e_return;
3386  }
3387  break;
3388  case AT_CNMI:
3389  ast_debug(1, "[%s] sms new message indication enabled\n", pvt->id);
3390  pvt->has_sms = 1;
3391  break;
3392  /* end initialization stuff */
3393 
3394  case AT_A:
3395  ast_debug(1, "[%s] answer sent successfully\n", pvt->id);
3396  pvt->needchup = 1;
3397  break;
3398  case AT_D:
3399  ast_debug(1, "[%s] dial sent successfully\n", pvt->id);
3400  pvt->needchup = 1;
3401  pvt->outgoing = 1;
3403  break;
3404  case AT_CHUP:
3405  ast_debug(1, "[%s] successful hangup\n", pvt->id);
3406  break;
3407  case AT_CMGS:
3408  ast_debug(1, "[%s] successfully sent sms message\n", pvt->id);
3409  pvt->outgoing_sms = 0;
3410  break;
3411  case AT_VTS:
3412  ast_debug(1, "[%s] digit sent successfully\n", pvt->id);
3413  break;
3414  case AT_CUSD:
3415  ast_debug(1, "[%s] CUSD code sent successfully\n", pvt->id);
3416  break;
3417  case AT_UNKNOWN:
3418  default:
3419  ast_debug(1, "[%s] received OK for unhandled request: %s\n", pvt->id, at_msg2str(entry->response_to));
3420  break;
3421  }
3423  } else if (entry) {
3424  ast_debug(1, "[%s] received AT message 'OK' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3425  } else {
3426  ast_debug(1, "[%s] received unexpected AT message 'OK'\n", pvt->id);
3427  }
3428  return 0;
3429 
3430 e_return:
3432  return -1;
3433 }
3434 
3435 /*!
3436  * \brief Handle ERROR AT messages.
3437  * \param pvt a mbl_pvt structure
3438  * \param buf a null terminated buffer containing an AT message
3439  * \retval 0 success
3440  * \retval -1 error
3441  */
3442 static int handle_response_error(struct mbl_pvt *pvt, char *buf)
3443 {
3444  struct msg_queue_entry *entry;
3445  if ((entry = msg_queue_head(pvt))
3446  && (entry->expected == AT_OK
3447  || entry->expected == AT_ERROR
3448  || entry->expected == AT_CMS_ERROR
3449  || entry->expected == AT_CMGR
3450  || entry->expected == AT_SMS_PROMPT)) {
3451  switch (entry->response_to) {
3452 
3453  /* initialization stuff */
3454  case AT_BRSF:
3455  ast_debug(1, "[%s] error reading BSRF\n", pvt->id);
3456  goto e_return;
3457  case AT_CIND_TEST:
3458  ast_debug(1, "[%s] error during CIND test\n", pvt->id);
3459  goto e_return;
3460  case AT_CIND:
3461  ast_debug(1, "[%s] error requesting CIND state\n", pvt->id);
3462  goto e_return;
3463  case AT_CMER:
3464  ast_debug(1, "[%s] error during CMER request\n", pvt->id);
3465  goto e_return;
3466  case AT_CLIP:
3467  ast_debug(1, "[%s] error enabling calling line indication\n", pvt->id);
3468  goto e_return;
3469  case AT_VGS:
3470  ast_debug(1, "[%s] volume level synchronization failed\n", pvt->id);
3471 
3472  /* this is not a fatal error, let's continue with initialization */
3473 
3474  /* set the SMS operating mode to text mode */
3475  if (hfp_send_cmgf(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMGF)) {
3476  ast_debug(1, "[%s] error setting CMGF\n", pvt->id);
3477  goto e_return;
3478  }
3479  break;
3480  case AT_CMGF:
3481  pvt->has_sms = 0;
3482  ast_debug(1, "[%s] error setting CMGF\n", pvt->id);
3483  ast_debug(1, "[%s] no SMS support\n", pvt->id);
3484  break;
3485  case AT_CNMI:
3486  pvt->has_sms = 0;
3487  ast_debug(1, "[%s] error setting CNMI\n", pvt->id);
3488  ast_debug(1, "[%s] no SMS support\n", pvt->id);
3489  break;
3490  case AT_ECAM:
3491  ast_debug(1, "[%s] Mobile does not support Sony Ericsson extensions\n", pvt->id);
3492 
3493  /* this is not a fatal error, let's continue with the initialization */
3494 
3495  if (hfp_send_vgs(pvt->hfp, 15) || msg_queue_push(pvt, AT_OK, AT_VGS)) {
3496  ast_debug(1, "[%s] error synchronizing gain settings\n", pvt->id);
3497  goto e_return;
3498  }
3499 
3500  pvt->timeout = -1;
3501  pvt->hfp->initialized = 1;
3502  ast_verb(3, "Bluetooth Device %s initialized and ready.\n", pvt->id);
3503 
3504  break;
3505  /* end initialization stuff */
3506 
3507  case AT_A:
3508  ast_debug(1, "[%s] answer failed\n", pvt->id);
3509  mbl_queue_hangup(pvt);
3510  break;
3511  case AT_D:
3512  ast_debug(1, "[%s] dial failed\n", pvt->id);
3513  pvt->needchup = 0;
3515  break;
3516  case AT_CHUP:
3517  ast_debug(1, "[%s] error sending hangup, disconnecting\n", pvt->id);
3518  goto e_return;
3519  case AT_CMGR:
3520  ast_debug(1, "[%s] error reading sms message\n", pvt->id);
3521  pvt->incoming_sms = 0;
3522  break;
3523  case AT_CMGS:
3524  ast_debug(1, "[%s] error sending sms message\n", pvt->id);
3525  pvt->outgoing_sms = 0;
3526  break;
3527  case AT_VTS:
3528  ast_debug(1, "[%s] error sending digit\n", pvt->id);
3529  break;
3530  case AT_CUSD:
3531  ast_verb(0, "[%s] error sending CUSD command\n", pvt->id);
3532  break;
3533  case AT_UNKNOWN:
3534  default:
3535  ast_debug(1, "[%s] received ERROR for unhandled request: %s\n", pvt->id, at_msg2str(entry->response_to));
3536  break;
3537  }
3539  } else if (entry) {
3540  ast_debug(1, "[%s] received AT message 'ERROR' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3541  } else {
3542  ast_debug(1, "[%s] received unexpected AT message 'ERROR'\n", pvt->id);
3543  }
3544 
3545  return 0;
3546 
3547 e_return:
3549  return -1;
3550 }
3551 
3552 /*!
3553  * \brief Handle AT+CIEV messages.
3554  * \param pvt a mbl_pvt structure
3555  * \param buf a null terminated buffer containing an AT message
3556  * \retval 0 success
3557  * \retval -1 error
3558  */
3559 static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
3560 {
3561  int i;
3562  switch (hfp_parse_ciev(pvt->hfp, buf, &i)) {
3563  case HFP_CIND_CALL:
3564  switch (i) {
3565  case HFP_CIND_CALL_NONE:
3566  ast_debug(1, "[%s] line disconnected\n", pvt->id);
3567  if (pvt->owner) {
3568  ast_debug(1, "[%s] hanging up owner\n", pvt->id);
3569  if (mbl_queue_hangup(pvt)) {
3570  ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
3571  return -1;
3572  }
3573  }
3574  pvt->needchup = 0;
3575  pvt->needcallerid = 0;
3576  pvt->incoming = 0;
3577  pvt->outgoing = 0;
3578  break;
3579  case HFP_CIND_CALL_ACTIVE:
3580  if (pvt->outgoing) {
3581  ast_debug(1, "[%s] remote end answered\n", pvt->id);
3583  } else if (pvt->incoming && pvt->answered) {
3585  } else if (pvt->incoming) {
3586  /* user answered from handset, disconnecting */
3587  ast_verb(3, "[%s] user answered bluetooth device from handset, disconnecting\n", pvt->id);
3588  mbl_queue_hangup(pvt);
3589  return -1;
3590  }
3591  break;
3592  }
3593  break;
3594 
3595  case HFP_CIND_CALLSETUP:
3596  switch (i) {
3598  if (pvt->hfp->cind_state[pvt->hfp->cind_map.call] != HFP_CIND_CALL_ACTIVE) {
3599  if (pvt->owner) {
3600  if (pvt->hfp->sent_alerting == 1) {
3601  handle_response_busy(pvt);
3602  }
3603  if (mbl_queue_hangup(pvt)) {
3604  ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
3605  return -1;
3606  }
3607  }
3608  pvt->needchup = 0;
3609  pvt->needcallerid = 0;
3610  pvt->incoming = 0;
3611  pvt->outgoing = 0;
3612  }
3613  break;
3615  ast_debug(1, "[%s] incoming call, waiting for caller id\n", pvt->id);
3616  pvt->needcallerid = 1;
3617  pvt->incoming = 1;
3618  break;
3620  if (pvt->outgoing) {
3621  pvt->hfp->sent_alerting = 0;
3622  ast_debug(1, "[%s] outgoing call\n", pvt->id);
3623  } else {
3624  ast_verb(3, "[%s] user dialed from handset, disconnecting\n", pvt->id);
3625  return -1;
3626  }
3627  break;
3629  if (pvt->outgoing) {
3630  ast_debug(1, "[%s] remote alerting\n", pvt->id);
3632  pvt->hfp->sent_alerting = 1;
3633  }
3634  break;
3635  }
3636  break;
3637  case HFP_CIND_NONE:
3638  ast_debug(1, "[%s] error parsing CIND: %s\n", pvt->id, buf);
3639  break;
3640  }
3641  return 0;
3642 }
3643 
3644 /*!
3645  * \brief Handle AT+CLIP messages.
3646  * \param pvt a mbl_pvt structure
3647  * \param buf a null terminated buffer containing an AT message
3648  * \retval 0 success
3649  * \retval -1 error
3650  */
3651 static int handle_response_clip(struct mbl_pvt *pvt, char *buf)
3652 {
3653  struct msg_queue_entry *msg;
3654  struct ast_channel *chan;
3655  struct cidinfo cidinfo;
3656 
3657  if ((msg = msg_queue_head(pvt)) && msg->expected == AT_CLIP) {
3659 
3660  pvt->needcallerid = 0;
3661  cidinfo = hfp_parse_clip(pvt->hfp, buf);
3662 
3663  if (!(chan = mbl_new(AST_STATE_RING, pvt, &cidinfo, NULL, NULL))) {
3664  ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);
3665  hfp_send_chup(pvt->hfp);
3666  msg_queue_push(pvt, AT_OK, AT_CHUP);
3667  return -1;
3668  }
3669 
3670  /* from this point on, we need to send a chup in the event of a
3671  * hangup */
3672  pvt->needchup = 1;
3673 
3674  if (ast_pbx_start(chan)) {
3675  ast_log(LOG_ERROR, "[%s] unable to start pbx on incoming call\n", pvt->id);
3676  mbl_ast_hangup(pvt);
3677  return -1;
3678  }
3679  }
3680 
3681  return 0;
3682 }
3683 
3684 /*!
3685  * \brief Handle RING messages.
3686  * \param pvt a mbl_pvt structure
3687  * \param buf a null terminated buffer containing an AT message
3688  * \retval 0 success
3689  * \retval -1 error
3690  */
3691 static int handle_response_ring(struct mbl_pvt *pvt, char *buf)
3692 {
3693  if (pvt->needcallerid) {
3694  ast_debug(1, "[%s] got ring while waiting for caller id\n", pvt->id);
3695  return msg_queue_push(pvt, AT_CLIP, AT_UNKNOWN);
3696  } else {
3697  return 0;
3698  }
3699 }
3700 
3701 /*!
3702  * \brief Handle AT+CMTI messages.
3703  * \param pvt a mbl_pvt structure
3704  * \param buf a null terminated buffer containing an AT message
3705  * \retval 0 success
3706  * \retval -1 error
3707  */
3708 static int handle_response_cmti(struct mbl_pvt *pvt, char *buf)
3709 {
3710  int index = hfp_parse_cmti(pvt->hfp, buf);
3711  if (index > 0) {
3712  ast_debug(1, "[%s] incoming sms message\n", pvt->id);
3713 
3714  if (hfp_send_cmgr(pvt->hfp, index)
3715  || msg_queue_push(pvt, AT_CMGR, AT_CMGR)) {
3716  ast_debug(1, "[%s] error sending CMGR to retrieve SMS message\n", pvt->id);
3717  return -1;
3718  }
3719 
3720  pvt->incoming_sms = 1;
3721  return 0;
3722  } else {
3723  ast_debug(1, "[%s] error parsing incoming sms message alert, disconnecting\n", pvt->id);
3724  return -1;
3725  }
3726 }
3727 
3728 /*!
3729  * \brief Handle AT+CMGR messages.
3730  * \param pvt a mbl_pvt structure
3731  * \param buf a null terminated buffer containing an AT message
3732  * \retval 0 success
3733  * \retval -1 error
3734  */
3735 static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf)
3736 {
3737  char *from_number = NULL, *text = NULL;
3738  struct ast_channel *chan;
3739  struct msg_queue_entry *msg;
3740 
3741  if ((msg = msg_queue_head(pvt)) && msg->expected == AT_CMGR) {
3743 
3744  if (hfp_parse_cmgr(pvt->hfp, buf, &from_number, &text)) {
3745  ast_debug(1, "[%s] error parsing sms message, disconnecting\n", pvt->id);
3746  return -1;
3747  }
3748 
3749  ast_debug(1, "[%s] successfully read sms message\n", pvt->id);
3750  pvt->incoming_sms = 0;
3751 
3752  /* XXX this channel probably does not need to be associated with this pvt */
3753  if (!(chan = mbl_new(AST_STATE_DOWN, pvt, NULL, NULL, NULL))) {
3754  ast_debug(1, "[%s] error creating sms message channel, disconnecting\n", pvt->id);
3755  return -1;
3756  }
3757 
3758  ast_channel_exten_set(chan, "sms");
3759  pbx_builtin_setvar_helper(chan, "SMSSRC", from_number);
3760  pbx_builtin_setvar_helper(chan, "SMSTXT", text);
3761 
3762  if (ast_pbx_start(chan)) {
3763  ast_log(LOG_ERROR, "[%s] unable to start pbx on incoming sms\n", pvt->id);
3764  mbl_ast_hangup(pvt);
3765  }
3766  } else {
3767  ast_debug(1, "[%s] got unexpected +CMGR message, ignoring\n", pvt->id);
3768  }
3769 
3770  return 0;
3771 }
3772 
3773 /*!
3774  * \brief Send an SMS message from the queue.
3775  * \param pvt a mbl_pvt structure
3776  * \param buf a null terminated buffer containing an AT message
3777  * \retval 0 success
3778  * \retval -1 error
3779  */
3780 static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf)
3781 {
3782  struct msg_queue_entry *msg;
3783  if (!(msg = msg_queue_head(pvt))) {
3784  ast_debug(1, "[%s] error, got sms prompt with no pending sms messages\n", pvt->id);
3785  return 0;
3786  }
3787 
3788  if (msg->expected != AT_SMS_PROMPT) {
3789  ast_debug(1, "[%s] error, got sms prompt but no pending sms messages\n", pvt->id);
3790  return 0;
3791  }
3792 
3793  if (hfp_send_sms_text(pvt->hfp, msg->data)
3794  || msg_queue_push(pvt, AT_OK, AT_CMGS)) {
3796  ast_debug(1, "[%s] error sending sms message\n", pvt->id);
3797  return 0;
3798  }
3799 
3801  return 0;
3802 }
3803 
3804 /*!
3805  * \brief Handle CUSD messages.
3806  * \param pvt a mbl_pvt structure
3807  * \param buf a null terminated buffer containing an AT message
3808  * \retval 0 success
3809  * \retval -1 error
3810  */
3811 static int handle_response_cusd(struct mbl_pvt *pvt, char *buf)
3812 {
3813  char *cusd;
3814 
3815  if (!(cusd = hfp_parse_cusd(pvt->hfp, buf))) {
3816  ast_verb(0, "[%s] error parsing CUSD: %s\n", pvt->id, buf);
3817  return 0;
3818  }
3819 
3820  ast_verb(0, "[%s] CUSD response: %s\n", pvt->id, cusd);
3821 
3822  return 0;
3823 }
3824 
3825 /*!
3826  * \brief Handle BUSY messages.
3827  * \param pvt a mbl_pvt structure
3828  * \retval 0 success
3829  * \retval -1 error
3830  */
3831 static int handle_response_busy(struct mbl_pvt *pvt)
3832 {
3834  pvt->needchup = 1;
3836  return 0;
3837 }
3838 
3839 /*!
3840  * \brief Handle NO DIALTONE messages.
3841  * \param pvt a mbl_pvt structure
3842  * \param buf a null terminated buffer containing an AT message
3843  * \retval 0 success
3844  * \retval -1 error
3845  */
3846 static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf)
3847 {
3848  ast_verb(1, "[%s] mobile reports NO DIALTONE\n", pvt->id);
3849  pvt->needchup = 1;
3851  return 0;
3852 }
3853 
3854 /*!
3855  * \brief Handle NO CARRIER messages.
3856  * \param pvt a mbl_pvt structure
3857  * \param buf a null terminated buffer containing an AT message
3858  * \retval 0 success
3859  * \retval -1 error
3860  */
3861 static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf)
3862 {
3863  ast_verb(1, "[%s] mobile reports NO CARRIER\n", pvt->id);
3864  pvt->needchup = 1;
3866  return 0;
3867 }
3868 
3869 
3870 static void *do_monitor_phone(void *data)
3871 {
3872  struct mbl_pvt *pvt = (struct mbl_pvt *)data;
3873  struct hfp_pvt *hfp = pvt->hfp;
3874  char buf[350];
3875  int t;
3876  at_message_t at_msg;
3877  struct msg_queue_entry *entry;
3878 
3879  /* Note: At one point the initialization procedure was neatly contained
3880  * in the hfp_init() function, but that initialization method did not
3881  * work with non standard devices. As a result, the initialization
3882  * procedure is not spread throughout the event handling loop.
3883  */
3884 
3885  /* start initialization with the BRSF request */
3886  ast_mutex_lock(&pvt->lock);
3887  pvt->timeout = 10000;
3888  if (hfp_send_brsf(hfp, &hfp_our_brsf) || msg_queue_push(pvt, AT_BRSF, AT_BRSF)) {
3889  ast_debug(1, "[%s] error sending BRSF\n", hfp->owner->id);
3890  goto e_cleanup;
3891  }
3892  ast_mutex_unlock(&pvt->lock);
3893 
3894  while (!check_unloading()) {
3895  ast_mutex_lock(&pvt->lock);
3896  t = pvt->timeout;
3897  ast_mutex_unlock(&pvt->lock);
3898 
3899  if (!rfcomm_wait(pvt->rfcomm_socket, &t)) {
3900  ast_debug(1, "[%s] timeout waiting for rfcomm data, disconnecting\n", pvt->id);
3901  ast_mutex_lock(&pvt->lock);
3902  if (!hfp->initialized) {
3903  if ((entry = msg_queue_head(pvt))) {
3904  switch (entry->response_to) {
3905  case AT_CIND_TEST:
3906  if (pvt->blackberry)
3907  ast_debug(1, "[%s] timeout during CIND test\n", hfp->owner->id);
3908  else
3909  ast_debug(1, "[%s] timeout during CIND test, try setting 'blackberry=yes'\n", hfp->owner->id);
3910  break;
3911  case AT_CMER:
3912  if (pvt->blackberry)
3913  ast_debug(1, "[%s] timeout after sending CMER, try setting 'blackberry=no'\n", hfp->owner->id);
3914  else
3915  ast_debug(1, "[%s] timeout after sending CMER\n", hfp->owner->id);
3916  break;
3917  default:
3918  ast_debug(1, "[%s] timeout while waiting for %s in response to %s\n", pvt->id, at_msg2str(entry->expected), at_msg2str(entry->response_to));
3919  break;
3920  }
3921  }
3922  }
3923  ast_mutex_unlock(&pvt->lock);
3924  goto e_cleanup;
3925  }
3926 
3927  if ((at_msg = at_read_full(hfp->rsock, buf, sizeof(buf))) < 0) {
3928  ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
3929  break;
3930  }
3931 
3932  ast_debug(1, "[%s] read %s\n", pvt->id, buf);
3933 
3934  switch (at_msg) {
3935  case AT_BRSF:
3936  ast_mutex_lock(&pvt->lock);
3937  if (handle_response_brsf(pvt, buf)) {
3938  ast_mutex_unlock(&pvt->lock);
3939  goto e_cleanup;
3940  }
3941  ast_mutex_unlock(&pvt->lock);
3942  break;
3943  case AT_CIND:
3944  ast_mutex_lock(&pvt->lock);
3945  if (handle_response_cind(pvt, buf)) {
3946  ast_mutex_unlock(&pvt->lock);
3947  goto e_cleanup;
3948  }
3949  ast_mutex_unlock(&pvt->lock);
3950  break;
3951  case AT_OK:
3952  ast_mutex_lock(&pvt->lock);
3953  if (handle_response_ok(pvt, buf)) {
3954  ast_mutex_unlock(&pvt->lock);
3955  goto e_cleanup;
3956  }
3957  ast_mutex_unlock(&pvt->lock);
3958  break;
3959  case AT_CMS_ERROR:
3960  case AT_ERROR:
3961  ast_mutex_lock(&pvt->lock);
3962  if (handle_response_error(pvt, buf)) {
3963  ast_mutex_unlock(&pvt->lock);
3964  goto e_cleanup;
3965  }
3966  ast_mutex_unlock(&pvt->lock);
3967  break;
3968  case AT_RING:
3969  ast_mutex_lock(&pvt->lock);
3970  if (handle_response_ring(pvt, buf)) {
3971  ast_mutex_unlock(&pvt->lock);
3972  goto e_cleanup;
3973  }
3974  ast_mutex_unlock(&pvt->lock);
3975  break;
3976  case AT_CIEV:
3977  ast_mutex_lock(&pvt->lock);
3978  if (handle_response_ciev(pvt, buf)) {
3979  ast_mutex_unlock(&pvt->lock);
3980  goto e_cleanup;
3981  }
3982  ast_mutex_unlock(&pvt->lock);
3983  break;
3984  case AT_CLIP:
3985  ast_mutex_lock(&pvt->lock);
3986  if (handle_response_clip(pvt, buf)) {
3987  ast_mutex_unlock(&pvt->lock);
3988  goto e_cleanup;
3989  }
3990  ast_mutex_unlock(&pvt->lock);
3991  break;
3992  case AT_CMTI:
3993  ast_mutex_lock(&pvt->lock);
3994  if (handle_response_cmti(pvt, buf)) {
3995  ast_mutex_unlock(&pvt->lock);
3996  goto e_cleanup;
3997  }
3998  ast_mutex_unlock(&pvt->lock);
3999  break;
4000  case AT_CMGR:
4001  ast_mutex_lock(&pvt->lock);
4002  if (handle_response_cmgr(pvt, buf)) {
4003  ast_mutex_unlock(&pvt->lock);
4004  goto e_cleanup;
4005  }
4006  ast_mutex_unlock(&pvt->lock);
4007  break;
4008  case AT_SMS_PROMPT:
4009  ast_mutex_lock(&pvt->lock);
4010  if (handle_sms_prompt(pvt, buf)) {
4011  ast_mutex_unlock(&pvt->lock);
4012  goto e_cleanup;
4013  }
4014  ast_mutex_unlock(&pvt->lock);
4015  break;
4016  case AT_CUSD:
4017  ast_mutex_lock(&pvt->lock);
4018  if (handle_response_cusd(pvt, buf)) {
4019  ast_mutex_unlock(&pvt->lock);
4020  goto e_cleanup;
4021  }
4022  ast_mutex_unlock(&pvt->lock);
4023  break;
4024  case AT_BUSY:
4025  ast_mutex_lock(&pvt->lock);
4026  if (handle_response_busy(pvt)) {
4027  ast_mutex_unlock(&pvt->lock);
4028  goto e_cleanup;
4029  }
4030  ast_mutex_unlock(&pvt->lock);
4031  break;
4032  case AT_NO_DIALTONE:
4033  ast_mutex_lock(&pvt->lock);
4034  if (handle_response_no_dialtone(pvt, buf)) {
4035  ast_mutex_unlock(&pvt->lock);
4036  goto e_cleanup;
4037  }
4038  ast_mutex_unlock(&pvt->lock);
4039  break;
4040  case AT_NO_CARRIER:
4041  ast_mutex_lock(&pvt->lock);
4042  if (handle_response_no_carrier(pvt, buf)) {
4043  ast_mutex_unlock(&pvt->lock);
4044  goto e_cleanup;
4045  }
4046  ast_mutex_unlock(&pvt->lock);
4047  break;
4048  case AT_ECAM:
4049  ast_mutex_lock(&pvt->lock);
4050  if (hfp_parse_ecav(hfp, buf) == 7) {
4051  if (handle_response_busy(pvt)) {
4052  ast_mutex_unlock(&pvt->lock);
4053  goto e_cleanup;
4054  }
4055  }
4056  ast_mutex_unlock(&pvt->lock);
4057  break;
4058  case AT_UNKNOWN:
4059  ast_debug(1, "[%s] ignoring unknown message: %s\n", pvt->id, buf);
4060  break;
4061  case AT_PARSE_ERROR:
4062  ast_debug(1, "[%s] error parsing message\n", pvt->id);
4063  goto e_cleanup;
4064  case AT_READ_ERROR:
4065  ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
4066  goto e_cleanup;
4067  default:
4068  break;
4069  }
4070  }
4071 
4072 e_cleanup:
4073 
4074  if (!hfp->initialized)
4075  ast_verb(3, "Error initializing Bluetooth device %s.\n", pvt->id);
4076 
4077  ast_mutex_lock(&pvt->lock);
4078  if (pvt->owner) {
4079  ast_debug(1, "[%s] device disconnected, hanging up owner\n", pvt->id);
4080  pvt->needchup = 0;
4081  mbl_queue_hangup(pvt);
4082  }
4083 
4084  close(pvt->rfcomm_socket);
4085  close(pvt->sco_socket);
4086  pvt->sco_socket = -1;
4087 
4088  msg_queue_flush(pvt);
4089 
4090  pvt->connected = 0;
4091  hfp->initialized = 0;
4092 
4093  pvt->adapter->inuse = 0;
4094  ast_mutex_unlock(&pvt->lock);
4095 
4096  ast_verb(3, "Bluetooth Device %s has disconnected.\n", pvt->id);
4097  manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
4098 
4099  return NULL;
4100 }
4101 
4102 static int headset_send_ring(const void *data)
4103 {
4104  struct mbl_pvt *pvt = (struct mbl_pvt *) data;
4105  ast_mutex_lock(&pvt->lock);
4106  if (!pvt->needring) {
4107  ast_mutex_unlock(&pvt->lock);
4108  return 0;
4109  }
4110  ast_mutex_unlock(&pvt->lock);
4111 
4112  if (hsp_send_ring(pvt->rfcomm_socket)) {
4113  ast_debug(1, "[%s] error sending RING\n", pvt->id);
4114  return 0;
4115  }
4116  return 1;
4117 }
4118 
4119 static void *do_monitor_headset(void *data)
4120 {
4121 
4122  struct mbl_pvt *pvt = (struct mbl_pvt *)data;
4123  char buf[256];
4124  int t;
4125  at_message_t at_msg;
4126  struct ast_channel *chan = NULL;
4127 
4128  ast_verb(3, "Bluetooth Device %s initialised and ready.\n", pvt->id);
4129 
4130  while (!check_unloading()) {
4131 
4132  t = ast_sched_wait(pvt->sched);
4133  if (t == -1) {
4134  t = 6000;
4135  }
4136 
4137  ast_sched_runq(pvt->sched);
4138 
4139  if (rfcomm_wait(pvt->rfcomm_socket, &t) == 0)
4140  continue;
4141 
4142  if ((at_msg = at_read_full(pvt->rfcomm_socket, buf, sizeof(buf))) < 0) {
4143  ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
4144  goto e_cleanup;
4145  }
4146  ast_debug(1, "[%s] %s\n", pvt->id, buf);
4147 
4148  switch (at_msg) {
4149  case AT_VGS:
4150  case AT_VGM:
4151  /* XXX volume change requested, we will just
4152  * pretend to do something with it */
4153  if (hsp_send_ok(pvt->rfcomm_socket)) {
4154  ast_debug(1, "[%s] error sending AT message 'OK'\n", pvt->id);
4155  goto e_cleanup;
4156  }
4157  break;
4158  case AT_CKPD:
4159  ast_mutex_lock(&pvt->lock);
4160  if (pvt->outgoing) {
4161  pvt->needring = 0;
4162  hsp_send_ok(pvt->rfcomm_socket);
4163  if (pvt->answered) {
4164  /* we have an answered call up to the
4165  * HS, he wants to hangup */
4166  mbl_queue_hangup(pvt);
4167  } else {
4168  /* we have an outgoing call to the HS,
4169  * he wants to answer */
4170  if ((pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr)) == -1) {
4171  ast_log(LOG_ERROR, "[%s] unable to create audio connection\n", pvt->id);
4172  mbl_queue_hangup(pvt);
4173  ast_mutex_unlock(&pvt->lock);
4174  goto e_cleanup;
4175  }
4176 
4177  ast_channel_set_fd(pvt->owner, 0, pvt->sco_socket);
4178 
4180  pvt->answered = 1;
4181 
4182  if (hsp_send_vgs(pvt->rfcomm_socket, 13) || hsp_send_vgm(pvt->rfcomm_socket, 13)) {
4183  ast_debug(1, "[%s] error sending VGS/VGM\n", pvt->id);
4184  mbl_queue_hangup(pvt);
4185  ast_mutex_unlock(&pvt->lock);
4186  goto e_cleanup;
4187  }
4188  }
4189  } else if (pvt->incoming) {
4190  /* we have an incoming call from the
4191  * HS, he wants to hang up */
4192  mbl_queue_hangup(pvt);
4193  } else {
4194  /* no call is up, HS wants to dial */
4195  hsp_send_ok(pvt->rfcomm_socket);
4196 
4197  if ((pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr)) == -1) {
4198  ast_log(LOG_ERROR, "[%s] unable to create audio connection\n", pvt->id);
4199  ast_mutex_unlock(&pvt->lock);
4200  goto e_cleanup;
4201  }
4202 
4203  pvt->incoming = 1;
4204 
4205  if (!(chan = mbl_new(AST_STATE_UP, pvt, NULL, NULL, NULL))) {
4206  ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);
4207  ast_mutex_unlock(&pvt->lock);
4208  goto e_cleanup;
4209  }
4210 
4211  ast_channel_set_fd(chan, 0, pvt->sco_socket);
4212 
4213  ast_channel_exten_set(chan, "s");
4214  if (ast_pbx_start(chan)) {
4215  ast_log(LOG_ERROR, "[%s] unable to start pbx on incoming call\n", pvt->id);
4216  ast_hangup(chan);
4217  ast_mutex_unlock(&pvt->lock);
4218  goto e_cleanup;
4219  }
4220  }
4221  ast_mutex_unlock(&pvt->lock);
4222  break;
4223  default:
4224  ast_debug(1, "[%s] received unknown AT command: %s (%s)\n", pvt->id, buf, at_msg2str(at_msg));
4225  if (hsp_send_error(pvt->rfcomm_socket)) {
4226  ast_debug(1, "[%s] error sending AT message 'ERROR'\n", pvt->id);
4227  goto e_cleanup;
4228  }
4229  break;
4230  }
4231  }
4232 
4233 e_cleanup:
4234  ast_mutex_lock(&pvt->lock);
4235  if (pvt->owner) {
4236  ast_debug(1, "[%s] device disconnected, hanging up owner\n", pvt->id);
4237  mbl_queue_hangup(pvt);
4238  }
4239 
4240 
4241  close(pvt->rfcomm_socket);
4242  close(pvt->sco_socket);
4243  pvt->sco_socket = -1;
4244 
4245  pvt->connected = 0;
4246 
4247  pvt->needring = 0;
4248  pvt->outgoing = 0;
4249  pvt->incoming = 0;
4250 
4251  pvt->adapter->inuse = 0;
4252  ast_mutex_unlock(&pvt->lock);
4253 
4254  manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
4255  ast_verb(3, "Bluetooth Device %s has disconnected\n", pvt->id);
4256 
4257  return NULL;
4258 
4259 }
4260 
4261 static int start_monitor(struct mbl_pvt *pvt)
4262 {
4263 
4264  if (pvt->type == MBL_TYPE_PHONE) {
4265  pvt->hfp->rsock = pvt->rfcomm_socket;
4266 
4269  return 0;
4270  }
4271  } else {
4274  return 0;
4275  }
4276  }
4277 
4278  return 1;
4279 
4280 }
4281 
4282 static void *do_discovery(void *data)
4283 {
4284 
4285  struct adapter_pvt *adapter;
4286  struct mbl_pvt *pvt;
4287 
4288  while (!check_unloading()) {
4290  AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4291  if (!adapter->inuse) {
4294  ast_mutex_lock(&pvt->lock);
4295  if (!adapter->inuse && !pvt->connected && !strcmp(adapter->id, pvt->adapter->id)) {
4296  if ((pvt->rfcomm_socket = rfcomm_connect(adapter->addr, pvt->addr, pvt->rfcomm_port)) > -1) {
4297  if (start_monitor(pvt)) {
4298  pvt->connected = 1;
4299  adapter->inuse = 1;
4300  manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Connect\r\nDevice: %s\r\n", pvt->id);
4301  ast_verb(3, "Bluetooth Device %s has connected, initializing...\n", pvt->id);
4302  }
4303  }
4304  }
4305  ast_mutex_unlock(&pvt->lock);
4306  }
4308  }
4309  }
4311 
4312 
4313  /* Go to sleep (only if we are not unloading) */
4314  if (!check_unloading())
4315  sleep(discovery_interval);
4316  }
4317 
4318  return NULL;
4319 }
4320 
4321 /*!
4322  * \brief Service new and existing SCO connections.
4323  * This thread accepts new sco connections and handles audio data. There is
4324  * one do_sco_listen thread for each adapter.
4325  */
4326 static void *do_sco_listen(void *data)
4327 {
4328  struct adapter_pvt *adapter = (struct adapter_pvt *) data;
4329 
4330  while (!check_unloading()) {
4331  /* check for new sco connections */
4332  if (ast_io_wait(adapter->accept_io, 0) == -1) {
4333  /* handle errors */
4334  ast_log(LOG_ERROR, "ast_io_wait() failed for adapter %s\n", adapter->id);
4335  break;
4336  }
4337 
4338  /* handle audio data */
4339  if (ast_io_wait(adapter->io, 1) == -1) {
4340  ast_log(LOG_ERROR, "ast_io_wait() failed for audio on adapter %s\n", adapter->id);
4341  break;
4342  }
4343  }
4344 
4345  return NULL;
4346 }
4347 
4348 /*
4349 
4350  Module
4351 
4352 */
4353 
4354 /*!
4355  * \brief Load an adapter from the configuration file.
4356  * \param cfg the config to load the adapter from
4357  * \param cat the adapter to load
4358  *
4359  * This function loads the given adapter and starts the sco listener thread for
4360  * that adapter.
4361  *
4362  * \return NULL on error, a pointer to the adapter that was loaded on success
4363  */
4364 static struct adapter_pvt *mbl_load_adapter(struct ast_config *cfg, const char *cat)
4365 {
4366  const char *id, *address;
4367  struct adapter_pvt *adapter;
4368  struct ast_variable *v;
4369  struct hci_dev_req dr;
4370  uint16_t vs;
4371 
4372  id = ast_variable_retrieve(cfg, cat, "id");
4373  address = ast_variable_retrieve(cfg, cat, "address");
4374 
4375  if (ast_strlen_zero(id) || ast_strlen_zero(address)) {
4376  ast_log(LOG_ERROR, "Skipping adapter. Missing id or address settings.\n");
4377  goto e_return;
4378  }
4379 
4380  ast_debug(1, "Reading configuration for adapter %s %s.\n", id, address);
4381 
4382  if (!(adapter = ast_calloc(1, sizeof(*adapter)))) {
4383  ast_log(LOG_ERROR, "Skipping adapter %s. Error allocating memory.\n", id);
4384  goto e_return;
4385  }
4386 
4387  ast_copy_string(adapter->id, id, sizeof(adapter->id));
4388  str2ba(address, &adapter->addr);
4389 
4390  /* attempt to connect to the adapter */
4391  adapter->dev_id = hci_devid(address);
4392  adapter->hci_socket = hci_open_dev(adapter->dev_id);
4393  if (adapter->dev_id < 0 || adapter->hci_socket < 0) {
4394  ast_log(LOG_ERROR, "Skipping adapter %s. Unable to communicate with adapter.\n", adapter->id);
4395  goto e_free_adapter;
4396  }
4397 
4398  /* check voice setting */
4399  hci_read_voice_setting(adapter->hci_socket, &vs, 1000);
4400  vs = htobs(vs);
4401  if (vs != 0x0060) {
4402  ast_log(LOG_ERROR, "Skipping adapter %s. Voice setting must be 0x0060 - see 'man hciconfig' for details.\n", adapter->id);
4403  goto e_hci_close_dev;
4404  }
4405 
4406  for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
4407  if (!strcasecmp(v->name, "forcemaster")) {
4408  if (ast_true(v->value)) {
4409  dr.dev_id = adapter->dev_id;
4410  if (hci_strtolm("master", &dr.dev_opt)) {
4411  if (ioctl(adapter->hci_socket, HCISETLINKMODE, (unsigned long) &dr) < 0) {
4412  ast_log(LOG_WARNING, "Unable to set adapter %s link mode to MASTER. Ignoring 'forcemaster' option.\n", adapter->id);
4413  }
4414  }
4415  }
4416  } else if (!strcasecmp(v->name, "alignmentdetection")) {
4417  adapter->alignment_detection = ast_true(v->value);
4418  }
4419  }
4420 
4421  /* create io contexts */
4422  if (!(adapter->accept_io = io_context_create())) {
4423  ast_log(LOG_ERROR, "Unable to create I/O context for audio connection listener\n");
4424  goto e_hci_close_dev;
4425  }
4426 
4427  if (!(adapter->io = io_context_create())) {
4428  ast_log(LOG_ERROR, "Unable to create I/O context for audio connections\n");
4429  goto e_destroy_accept_io;
4430  }
4431 
4432  /* bind the sco listener socket */
4433  if (sco_bind(adapter) < 0) {
4434  ast_log(LOG_ERROR, "Skipping adapter %s. Error binding audio connection listerner socket.\n", adapter->id);
4435  goto e_destroy_io;
4436  }
4437 
4438  /* add the socket to the io context */
4439  if (!(adapter->sco_id = ast_io_add(adapter->accept_io, adapter->sco_socket, sco_accept, AST_IO_IN, adapter))) {
4440  ast_log(LOG_ERROR, "Skipping adapter %s. Error adding listener socket to I/O context.\n", adapter->id);
4441  goto e_close_sco;
4442  }
4443 
4444  /* start the sco listener for this adapter */
4446  ast_log(LOG_ERROR, "Skipping adapter %s. Error creating audio connection listerner thread.\n", adapter->id);
4447  goto e_remove_sco;
4448  }
4449 
4450  /* add the adapter to our global list */
4454  ast_debug(1, "Loaded adapter %s %s.\n", adapter->id, address);
4455 
4456  return adapter;
4457 
4458 e_remove_sco:
4459  ast_io_remove(adapter->accept_io, adapter->sco_id);
4460 e_close_sco:
4461  close(adapter->sco_socket);
4462 e_destroy_io:
4463  io_context_destroy(adapter->io);
4464 e_destroy_accept_io:
4465  io_context_destroy(adapter->accept_io);
4466 e_hci_close_dev:
4467  hci_close_dev(adapter->hci_socket);
4468 e_free_adapter:
4469  ast_free(adapter);
4470 e_return:
4471  return NULL;
4472 }
4473 
4474 /*!
4475  * \brief Load a device from the configuration file.
4476  * \param cfg the config to load the device from
4477  * \param cat the device to load
4478  * \return NULL on error, a pointer to the device that was loaded on success
4479  */
4480 static struct mbl_pvt *mbl_load_device(struct ast_config *cfg, const char *cat)
4481 {
4482  struct mbl_pvt *pvt;
4483  struct adapter_pvt *adapter;
4484  struct ast_variable *v;
4485  const char *address, *adapter_str, *port;
4486  ast_debug(1, "Reading configuration for device %s.\n", cat);
4487 
4488  adapter_str = ast_variable_retrieve(cfg, cat, "adapter");
4489  if(ast_strlen_zero(adapter_str)) {
4490  ast_log(LOG_ERROR, "Skipping device %s. No adapter specified.\n", cat);
4491  goto e_return;
4492  }
4493 
4494  /* find the adapter */
4496  AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4497  if (!strcmp(adapter->id, adapter_str))
4498  break;
4499  }
4501  if (!adapter) {
4502  ast_log(LOG_ERROR, "Skiping device %s. Unknown adapter '%s' specified.\n", cat, adapter_str);
4503  goto e_return;
4504  }
4505 
4506  address = ast_variable_retrieve(cfg, cat, "address");
4507  port = ast_variable_retrieve(cfg, cat, "port");
4508  if (ast_strlen_zero(port) || ast_strlen_zero(address)) {
4509  ast_log(LOG_ERROR, "Skipping device %s. Missing required port or address setting.\n", cat);
4510  goto e_return;
4511  }
4512 
4513  /* create and initialize our pvt structure */
4514  if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
4515  ast_log(LOG_ERROR, "Skipping device %s. Error allocating memory.\n", cat);
4516  goto e_return;
4517  }
4518 
4519  ast_mutex_init(&pvt->lock);
4521 
4522  /* set some defaults */
4523 
4524  pvt->type = MBL_TYPE_PHONE;
4525  ast_copy_string(pvt->context, "default", sizeof(pvt->context));
4526 
4527  /* populate the pvt structure */
4528  pvt->adapter = adapter;
4529  ast_copy_string(pvt->id, cat, sizeof(pvt->id));
4530  str2ba(address, &pvt->addr);
4531  pvt->timeout = -1;
4532  pvt->rfcomm_socket = -1;
4533  pvt->rfcomm_port = atoi(port);
4534  pvt->sco_socket = -1;
4536  pvt->ring_sched_id = -1;
4537  pvt->has_sms = 1;
4538 
4539  /* setup the bt_out_smoother */
4541  ast_log(LOG_ERROR, "Skipping device %s. Error setting up frame bt_out_smoother.\n", cat);
4542  goto e_free_pvt;
4543  }
4544 
4545  /* setup the bt_in_smoother */
4547  ast_log(LOG_ERROR, "Skipping device %s. Error setting up frame bt_in_smoother.\n", cat);
4548  goto e_free_bt_out_smoother;
4549  }
4550 
4551  /* setup the dsp */
4552  if (!(pvt->dsp = ast_dsp_new())) {
4553  ast_log(LOG_ERROR, "Skipping device %s. Error setting up dsp for dtmf detection.\n", cat);
4554  goto e_free_bt_in_smoother;
4555  }
4556 
4557  /* setup the scheduler */
4558  if (!(pvt->sched = ast_sched_context_create())) {
4559  ast_log(LOG_ERROR, "Unable to create scheduler context for headset device\n");
4560  goto e_free_dsp;
4561  }
4562 
4565 
4566  for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
4567  if (!strcasecmp(v->name, "type")) {
4568  if (!strcasecmp(v->value, "headset"))
4569  pvt->type = MBL_TYPE_HEADSET;
4570  else
4571  pvt->type = MBL_TYPE_PHONE;
4572  } else if (!strcasecmp(v->name, "context")) {
4573  ast_copy_string(pvt->context, v->value, sizeof(pvt->context));
4574  } else if (!strcasecmp(v->name, "group")) {
4575  /* group is set to 0 if invalid */
4576  pvt->group = atoi(v->value);
4577  } else if (!strcasecmp(v->name, "sms")) {
4578  pvt->has_sms = ast_true(v->value);
4579  } else if (!strcasecmp(v->name, "nocallsetup")) {
4580  pvt->no_callsetup = ast_true(v->value);
4581 
4582  if (pvt->no_callsetup)
4583  ast_debug(1, "Setting nocallsetup mode for device %s.\n", pvt->id);
4584  } else if (!strcasecmp(v->name, "blackberry")) {
4585  pvt->blackberry = ast_true(v->value);
4586  pvt->has_sms = 0;
4587  }
4588  }
4589 
4590  if (pvt->type == MBL_TYPE_PHONE) {
4591  if (!(pvt->hfp = ast_calloc(1, sizeof(*pvt->hfp)))) {
4592  ast_log(LOG_ERROR, "Skipping device %s. Error allocating memory.\n", pvt->id);
4593  goto e_free_sched;
4594  }
4595 
4596  pvt->hfp->owner = pvt;
4597  pvt->hfp->rport = pvt->rfcomm_port;
4598  pvt->hfp->nocallsetup = pvt->no_callsetup;
4599  } else {
4600  pvt->has_sms = 0;
4601  }
4602 
4606  ast_debug(1, "Loaded device %s.\n", pvt->id);
4607 
4608  return pvt;
4609 
4610 e_free_sched:
4612 e_free_dsp:
4613  ast_dsp_free(pvt->dsp);
4614 e_free_bt_in_smoother:
4616 e_free_bt_out_smoother:
4618 e_free_pvt:
4619  ast_free(pvt);
4620 e_return:
4621  return NULL;
4622 }
4623 
4624 static int mbl_load_config(void)
4625 {
4626  struct ast_config *cfg;
4627  const char *cat;
4628  struct ast_variable *v;
4629  struct ast_flags config_flags = { 0 };
4630 
4631  cfg = ast_config_load(MBL_CONFIG, config_flags);
4632  if (!cfg) {
4633  cfg = ast_config_load(MBL_CONFIG_OLD, config_flags);
4634  }
4635  if (!cfg)
4636  return -1;
4637 
4638  /* parse [general] section */
4639  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4640  if (!strcasecmp(v->name, "interval")) {
4641  if (!sscanf(v->value, "%d", &discovery_interval)) {
4642  ast_log(LOG_NOTICE, "error parsing 'interval' in general section, using default value\n");
4643  }
4644  }
4645  }
4646 
4647  /* load adapters */
4648  for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
4649  if (!strcasecmp(cat, "adapter")) {
4650  mbl_load_adapter(cfg, cat);
4651  }
4652  }
4653 
4654  if (AST_RWLIST_EMPTY(&adapters)) {
4656  "***********************************************************************\n"
4657  "No adapters could be loaded from the configuration file.\n"
4658  "Please review mobile.conf. See sample for details.\n"
4659  "***********************************************************************\n"
4660  );
4661  ast_config_destroy(cfg);
4662  return -1;
4663  }
4664 
4665  /* now load devices */
4666  for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
4667  if (strcasecmp(cat, "general") && strcasecmp(cat, "adapter")) {
4668  mbl_load_device(cfg, cat);
4669  }
4670  }
4671 
4672  ast_config_destroy(cfg);
4673 
4674  return 0;
4675 }
4676 
4677 /*!
4678  * \brief Check if the module is unloading.
4679  * \retval 0 not unloading
4680  * \retval 1 unloading
4681  */
4682 static inline int check_unloading()
4683 {
4684  int res;
4686  res = unloading_flag;
4688 
4689  return res;
4690 }
4691 
4692 /*!
4693  * \brief Set the unloading flag.
4694  */
4695 static inline void set_unloading()
4696 {
4698  unloading_flag = 1;
4700 }
4701 
4702 static int unload_module(void)
4703 {
4704  struct mbl_pvt *pvt;
4705  struct adapter_pvt *adapter;
4706 
4707  /* First, take us out of the channel loop */
4708  ast_channel_unregister(&mbl_tech);
4709 
4710  /* Unregister the CLI & APP */
4711  ast_cli_unregister_multiple(mbl_cli, sizeof(mbl_cli) / sizeof(mbl_cli[0]));
4714 
4715  /* signal everyone we are unloading */
4716  set_unloading();
4717 
4718  /* Kill the discovery thread */
4720  pthread_kill(discovery_thread, SIGURG);
4721  pthread_join(discovery_thread, NULL);
4722  }
4723 
4724  /* stop the sco listener threads */
4726  AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4727  pthread_kill(adapter->sco_listener_thread, SIGURG);
4728  pthread_join(adapter->sco_listener_thread, NULL);
4729  }
4731 
4732  /* Destroy the device list */
4734  while ((pvt = AST_RWLIST_REMOVE_HEAD(&devices, entry))) {
4735  if (pvt->monitor_thread != AST_PTHREADT_NULL) {
4736  pthread_kill(pvt->monitor_thread, SIGURG);
4737  pthread_join(pvt->monitor_thread, NULL);
4738  }
4739 
4740  close(pvt->sco_socket);
4741  close(pvt->rfcomm_socket);
4742 
4743  msg_queue_flush(pvt);
4744 
4745  if (pvt->hfp) {
4746  ast_free(pvt->hfp);
4747  }
4748 
4751  ast_dsp_free(pvt->dsp);
4753  ast_free(pvt);
4754  }
4756 
4757  /* Destroy the adapter list */
4759  while ((adapter = AST_RWLIST_REMOVE_HEAD(&adapters, entry))) {
4760  close(adapter->sco_socket);
4761  io_context_destroy(adapter->io);
4762  io_context_destroy(adapter->accept_io);
4763  hci_close_dev(adapter->hci_socket);
4764  ast_free(adapter);
4765  }
4767 
4768  if (sdp_session)
4769  sdp_close(sdp_session);
4770 
4771  ao2_ref(mbl_tech.capabilities, -1);
4772  mbl_tech.capabilities = NULL;
4773  return 0;
4774 }
4775 
4776 static int load_module(void)
4777 {
4778 
4779  int dev_id, s;
4780 
4782  return AST_MODULE_LOAD_DECLINE;
4783  }
4784 
4786  /* Check if we have Bluetooth, no point loading otherwise... */
4787  dev_id = hci_get_route(NULL);
4788 
4789  s = hci_open_dev(dev_id);
4790  if (dev_id < 0 || s < 0) {
4791  ast_log(LOG_ERROR, "No Bluetooth devices found. Not loading module.\n");
4792  ao2_ref(mbl_tech.capabilities, -1);
4793  mbl_tech.capabilities = NULL;
4794  hci_close_dev(s);
4795  return AST_MODULE_LOAD_DECLINE;
4796  }
4797 
4798  hci_close_dev(s);
4799 
4800  if (mbl_load_config()) {
4801  ast_log(LOG_ERROR, "Errors reading config file %s. Not loading module.\n", MBL_CONFIG);
4802  ao2_ref(mbl_tech.capabilities, -1);
4803  mbl_tech.capabilities = NULL;
4804  return AST_MODULE_LOAD_DECLINE;
4805  }
4806 
4808 
4809  /* Spin the discovery thread */
4811  ast_log(LOG_ERROR, "Unable to create discovery thread.\n");
4812  goto e_cleanup;
4813  }
4814 
4815  /* register our channel type */
4816  if (ast_channel_register(&mbl_tech)) {
4817  ast_log(LOG_ERROR, "Unable to register channel class %s\n", "Mobile");
4818  goto e_cleanup;
4819  }
4820 
4821  ast_cli_register_multiple(mbl_cli, sizeof(mbl_cli) / sizeof(mbl_cli[0]));
4824 
4825  return AST_MODULE_LOAD_SUCCESS;
4826 
4827 e_cleanup:
4828  unload_module();
4829 
4830  return AST_MODULE_LOAD_DECLINE;
4831 }
4832 
4833 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Bluetooth Mobile Device Channel Driver",
4834  .support_level = AST_MODULE_SUPPORT_EXTENDED,
4835  .load = load_module,
4836  .unload = unload_module,
4837  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
4838 );
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
int rfcomm_port
Definition: chan_mobile.c:131
struct ast_variable * next
int alignment_count
Definition: chan_mobile.c:146
static int mbl_queue_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1334
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
static int handle_response_busy(struct mbl_pvt *pvt)
Handle BUSY messages.
Definition: chan_mobile.c:3831
char context[AST_MAX_CONTEXT]
Definition: chan_mobile.c:129
static const char type[]
Definition: chan_ooh323.c:109
enum sip_cc_notify_state state
Definition: chan_sip.c:959
static int handle_response_cind(struct mbl_pvt *pvt, char *buf)
Handle the CIND response.
Definition: chan_mobile.c:3231
static int rfcomm_read_until_ok(int rsock, char **buf, size_t count, size_t *in_count)
Read until a.
Definition: chan_mobile.c:1609
int control
Definition: chan_mobile.c:309
char digit
static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
Handle AT+CIEV messages.
Definition: chan_mobile.c:3559
#define HFP_CIND_CALL
Definition: chan_mobile.c:278
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1494
Main Channel structure associated with a channel.
#define HFP_CIND_CALL_ACTIVE
Definition: chan_mobile.c:287
#define HFP_HF_CID
Definition: chan_mobile.c:259
int status
Definition: chan_mobile.c:308
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf)
Handle NO CARRIER messages.
Definition: chan_mobile.c:3861
int sco_socket
Definition: chan_mobile.c:137
static int hfp_send_dtmf(struct hfp_pvt *hfp, char digit)
Send a DTMF command.
Definition: chan_mobile.c:2596
static int hfp_send_atd(struct hfp_pvt *hfp, const char *number)
Send ATD.
Definition: chan_mobile.c:2691
const char *const type
Definition: channel.h:630
#define AST_CAUSE_INCOMPATIBLE_DESTINATION
Definition: causes.h:134
#define CHANNEL_FRAME_SIZE
Definition: chan_mobile.c:83
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define HFP_CIND_BATTCHG
Definition: chan_mobile.c:283
#define HFP_CIND_SIGNAL
Definition: chan_mobile.c:281
static int rfcomm_read_result(int rsock, char **buf, size_t count, size_t *in_count)
Read and AT result code.
Definition: chan_mobile.c:1725
static int sco_connect(bdaddr_t src, bdaddr_t dst)
Definition: chan_mobile.c:1833
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: chan_mobile.c:1088
char id[31]
Definition: chan_mobile.c:102
static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel)
Definition: chan_mobile.c:1390
#define ast_smoother_feed(s, f)
Definition: smoother.h:76
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
static int rfcomm_wait(int rsock, int *ms)
Wait for activity on an rfcomm socket.
Definition: chan_mobile.c:1479
static struct ast_cli_entry mbl_cli[]
Definition: chan_mobile.c:193
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
#define HFP_CIND_NONE
Definition: chan_mobile.c:276
static int load_module(void)
Definition: chan_mobile.c:4776
struct ast_smoother * bt_in_smoother
Definition: chan_mobile.c:136
static char * hfp_parse_cusd(struct hfp_pvt *hfp, char *buf)
Parse a CUSD answer.
Definition: chan_mobile.c:2416
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
#define HFP_HF_STATUS
Definition: chan_mobile.c:262
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
#define HFP_CIND_ROAM
Definition: chan_mobile.c:282
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void * ast_channel_tech_pvt(const struct ast_channel *chan)
unsigned int connected
Definition: chan_mobile.c:161
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
Device state management.
#define HFP_AG_ERRORS
Definition: chan_mobile.c:273
static struct mbl_pvt * mbl_load_device(struct ast_config *cfg, const char *cat)
Load a device from the configuration file.
Definition: chan_mobile.c:4480
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
char * address
Definition: f2c.h:59
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
int cind_index[16]
Definition: chan_mobile.c:349
int ecnr
Definition: chan_mobile.c:317
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
static struct hfp_hf hfp_our_brsf
Definition: chan_mobile.c:361
static struct ast_channel * mbl_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Definition: chan_mobile.c:898
Convenient Signal Processing routines.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
int volume
Definition: chan_mobile.c:307
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
static int hfp_parse_cind_test(struct hfp_pvt *hfp, char *buf)
Parse the result of the AT+CIND=? command.
Definition: chan_mobile.c:2818
int ecnr
Definition: chan_mobile.c:303
struct io_context * accept_io
Definition: chan_mobile.c:107
static int handle_response_brsf(struct mbl_pvt *pvt, char *buf)
Handle the BRSF response.
Definition: chan_mobile.c:3196
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:374
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
#define HFP_AG_ECNR
Definition: chan_mobile.c:266
static int indicator
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
#define HFP_CIND_CALLSETUP
Definition: chan_mobile.c:279
int cid
Definition: chan_mobile.c:305
unsigned int answered
Definition: chan_mobile.c:160
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
pthread_t sco_listener_thread
Definition: chan_mobile.c:110
static int check_unloading(void)
Check if the module is unloading.
Definition: chan_mobile.c:4682
static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen)
Definition: chan_mobile.c:1281
static int unloading_flag
Definition: chan_mobile.c:90
static int timeout
Definition: cdr_mysql.c:86
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static char * handle_cli_mobile_cusd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mobile.c:659
#define FORMAT2
int rsock
Definition: chan_mobile.c:352
static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf)
Parse BRSF data.
Definition: chan_mobile.c:2724
Structure for variables, used for configurations and for channel variables.
unsigned int blackberry
Definition: chan_mobile.c:144
static int hsp_send_vgs(int rsock, int gain)
Send a speaker gain unsolicited AT response.
Definition: chan_mobile.c:2943
struct ast_dsp * dsp
Definition: chan_mobile.c:148
static int hfp_send_cind(struct hfp_pvt *hfp)
Send the CIND read command.
Definition: chan_mobile.c:2525
#define HFP_HF_VOICE
Definition: chan_mobile.c:260
#define HFP_CIND_UNKNOWN
Definition: chan_mobile.c:275
#define AST_IO_IN
Definition: io.h:34
static int handle_response_cmti(struct mbl_pvt *pvt, char *buf)
Handle AT+CMTI messages.
Definition: chan_mobile.c:3708
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1797
Definition: cli.h:152
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
static int mbl_hangup(struct ast_channel *ast)
Definition: chan_mobile.c:1028
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
ast_channel_state
ast_channel states
Definition: channelstate.h:35
int hangupcause
Definition: chan_mobile.c:150
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:162
int timeout
Definition: chan_mobile.c:139
int nocallsetup
Definition: chan_mobile.c:347
unsigned int do_alignment_detection
Definition: chan_mobile.c:142
static const struct adsi_event events[]
Definition: app_adsiprog.c:85
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define HFP_CIND_CALL_NONE
Definition: chan_mobile.c:286
#define HFP_AG_CONTROL
Definition: chan_mobile.c:272
static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)
Definition: chan_mobile.c:1167
ast_control_frame_type
Internal control frame subtype field values.
static int hfp_send_cmer(struct hfp_pvt *hfp, int status)
Enable or disable indicator events reporting.
Definition: chan_mobile.c:2544
static int rfcomm_write_full(int rsock, char *buf, size_t count)
Write to an rfcomm socket.
Definition: chan_mobile.c:1454
#define ast_mutex_lock(a)
Definition: lock.h:187
unsigned int inuse
Definition: chan_mobile.c:104
static int hfp_send_ata(struct hfp_pvt *hfp)
Send ATA.
Definition: chan_mobile.c:2702
static struct test_val c
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
Definition: muted.c:95
char * text
Definition: app_queue.c:1508
#define ast_str_alloca(init_len)
Definition: strings.h:800
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
int cw
Definition: chan_mobile.c:304
static int hfp_send_sms_text(struct hfp_pvt *hfp, const char *message)
Send the text of an SMS message.
Definition: chan_mobile.c:2670
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
const char * args
#define NULL
Definition: resample.c:96
const char * data
#define rfcomm_read_debug(c)
Definition: chan_mobile.c:1501
I/O Management (derived from Cheops-NG)
static sdp_session_t * sdp_session
Definition: chan_mobile.c:87
int rfcomm_socket
Definition: chan_mobile.c:132
int value
Definition: syslog.c:37
static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf)
Handle NO DIALTONE messages.
Definition: chan_mobile.c:3846
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static int hsp_send_error(int rsock)
Send an ERROR AT response.
Definition: chan_mobile.c:2933
static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf)
Handle AT+CMGR messages.
Definition: chan_mobile.c:3735
unsigned int incoming
Definition: chan_mobile.c:154
static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_mobile.c:1195
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static int at_match_prefix(char *buf, char *prefix)
Match the given buffer with the given prefix.
Definition: chan_mobile.c:2003
#define HFP_CIND_CALLSETUP_ALERTING
Definition: chan_mobile.c:293
#define HFP_AG_CW
Definition: chan_mobile.c:265
Asterisk internal frame definitions.
#define ast_verb(level,...)
Definition: logger.h:463
static int sco_bind(struct adapter_pvt *adapter)
Bind an SCO listener socket for the given adapter.
Definition: chan_mobile.c:1958
struct ast_frame_subclass subclass
int * sco_id
Definition: chan_mobile.c:108
static int mbl_ast_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1354
short alignment_samples[4]
Definition: chan_mobile.c:145
static int mbl_answer(struct ast_channel *ast)
Definition: chan_mobile.c:1066
Utility functions.
#define HFP_HF_CW
Definition: chan_mobile.c:258
#define FORMAT1
#define ast_strlen_zero(foo)
Definition: strings.h:52
static pthread_t discovery_thread
Definition: chan_mobile.c:86
static int parse_next_token(char string[], const int start, const char delim)
Terminate current token and return an index to start of the next token.
Definition: chan_mobile.c:2297
char * cnam
Definition: chan_mobile.c:169
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:583
#define HFP_HF_ECNR
Definition: chan_mobile.c:257
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
Number structure.
Definition: app_followme.c:154
static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf)
Parse a CMTI notification.
Definition: chan_mobile.c:2326
mbl_type
Definition: chan_mobile.c:94
static int headset_send_ring(const void *data)
Definition: chan_mobile.c:4102
static int hfp_parse_cind_indicator(struct hfp_pvt *hfp, int group, char *indicator)
Parse and store the given indicator.
Definition: chan_mobile.c:2742
static struct adapter_pvt * mbl_load_adapter(struct ast_config *cfg, const char *cat)
Load an adapter from the configuration file.
Definition: chan_mobile.c:4364
static int mbl_status_exec(struct ast_channel *ast, const char *data)
Definition: chan_mobile.c:715
int reject
Definition: chan_mobile.c:321
Configuration File Parser.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
#define HFP_AG_REJECT
Definition: chan_mobile.c:270
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: main/utils.c:1639
static int hfp_send_clip(struct hfp_pvt *hfp, int status)
Enable or disable calling line identification.
Definition: chan_mobile.c:2583
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
static struct ast_frame * mbl_read(struct ast_channel *ast)
Definition: chan_mobile.c:1109
static int handle_response_cusd(struct mbl_pvt *pvt, char *buf)
Handle CUSD messages.
Definition: chan_mobile.c:3811
bdaddr_t addr
Definition: chan_mobile.c:127
#define ast_config_load(filename, flags)
Load a config file.
static int rfcomm_read_and_append_char(int rsock, char **buf, size_t count, size_t *in_count, char *result, char expected)
Read a character from the given stream and append it to the given buffer if it matches the expected c...
Definition: chan_mobile.c:1544
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
Definition: channel.c:2989
static void * do_monitor_phone(void *data)
Definition: chan_mobile.c:3870
General Asterisk PBX channel definitions.
struct adapter_pvt::@4 entry
void ast_channel_rings_set(struct ast_channel *chan, int value)
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:107
const char * src
static int hfp_send_vgs(struct hfp_pvt *hfp, int value)
Send the current speaker gain level.
Definition: chan_mobile.c:2556
#define ast_mutex_trylock(a)
Definition: lock.h:189
struct mbl_pvt * owner
Definition: chan_mobile.c:345
unsigned int no_callsetup
Definition: chan_mobile.c:140
const int fd
Definition: cli.h:159
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
Definition: dsp.c:405
int control
Definition: chan_mobile.c:323
#define AST_PTHREADT_NULL
Definition: lock.h:66
static int handle_response_clip(struct mbl_pvt *pvt, char *buf)
Handle AT+CLIP messages.
Definition: chan_mobile.c:3651
static struct ast_mansession session
static int hsp_send_vgm(int rsock, int gain)
Send a microphone gain unsolicited AT response.
Definition: chan_mobile.c:2955
#define ast_register_application(app, execute, synopsis, description)
Register an application.
Definition: module.h:610
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:71
#define HFP_AG_RING
Definition: chan_mobile.c:268
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
static int hfp_send_brsf(struct hfp_pvt *hfp, struct hfp_hf *brsf)
Send a BRSF request.
Definition: chan_mobile.c:2514
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
long int ast_random(void)
Definition: main/utils.c:2064
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
unsigned int has_sms
Definition: chan_mobile.c:141
#define DEVICE_FRAME_FORMAT
Definition: chan_mobile.c:82
#define MBL_CONFIG_OLD
Definition: chan_mobile.c:79
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int handle_response_ring(struct mbl_pvt *pvt, char *buf)
Handle RING messages.
Definition: chan_mobile.c:3691
int sent_alerting
Definition: chan_mobile.c:354
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
struct io_context * io
Definition: chan_mobile.c:106
int battchg
Definition: chan_mobile.c:337
A set of macros to manage forward-linked lists.
unsigned int alignment_detection
Definition: chan_mobile.c:105
static int hfp_brsf2int(struct hfp_hf *hf)
Convert a hfp_hf struct to a BRSF int.
Definition: chan_mobile.c:2468
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static int sco_accept(int *id, int fd, short events, void *data)
Accept SCO connections. This function is an ast_io callback function used to accept incoming sco audi...
Definition: chan_mobile.c:1898
int ring
Definition: chan_mobile.c:319
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
Parse a ECAV event.
Definition: chan_mobile.c:2164
static int discovery_interval
Definition: chan_mobile.c:85
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
This struct holds mappings for indications.
Definition: chan_mobile.c:330
#define AST_CAUSE_FACILITY_NOT_IMPLEMENTED
Definition: causes.h:132
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
static int handle_response_ok(struct mbl_pvt *pvt, char *buf)
Handle OK AT messages.
Definition: chan_mobile.c:3273
Core PBX routines and definitions.
static struct msg_queue_entry * msg_queue_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue.
Definition: chan_mobile.c:3023
int initialized
Definition: chan_mobile.c:346
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
This struct holds HFP features that we support.
Definition: chan_mobile.c:302
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
static int rfcomm_read_sms_prompt(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of an AT SMS prompt.
Definition: chan_mobile.c:1593
const char *const * argv
Definition: cli.h:161
static int sco_write(int s, char *buf, int len)
Definition: chan_mobile.c:1871
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
static int mbl_devicestate(const char *data)
Definition: chan_mobile.c:1214
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
static ast_mutex_t unload_mutex
Definition: chan_mobile.c:89
int callheld
Definition: chan_mobile.c:334
static int rfcomm_read_cmgr(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of a +CMGR message.
Definition: chan_mobile.c:1706
static char * mblsendsms_synopsis
Definition: chan_mobile.c:210
int callsetup
Definition: chan_mobile.c:333
#define HFP_AG_VOICE
Definition: chan_mobile.c:267
#define LOG_ERROR
Definition: logger.h:285
static char * app_mblstatus
Definition: chan_mobile.c:201
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static int hfp_send_cind_test(struct hfp_pvt *hfp)
Send the CIND test command.
Definition: chan_mobile.c:2534
int cind_state[16]
Definition: chan_mobile.c:350
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
at_message_t expected
Definition: chan_mobile.c:461
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct hfp_cind cind_map
Definition: chan_mobile.c:351
#define CLI_SHOWUSAGE
Definition: cli.h:45
struct ast_channel * owner
Definition: chan_mobile.c:119
char id[31]
Definition: chan_mobile.c:125
at_message_t response_to
Definition: chan_mobile.c:462
#define DEVICE_FRAME_SIZE
Definition: chan_mobile.c:81
static int rfcomm_read_until_crlf(int rsock, char **buf, size_t count, size_t *in_count)
Read until.
Definition: chan_mobile.c:1564
unsigned int needchup
Definition: chan_mobile.c:158
static int hsp_send_ring(int rsock)
Send a RING unsolicited AT response.
Definition: chan_mobile.c:2966
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
static char * handle_cli_mobile_search(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mobile.c:541
static int start_monitor(struct mbl_pvt *pvt)
Definition: chan_mobile.c:4261
char io_buf[CHANNEL_FRAME_SIZE+AST_FRIENDLY_OFFSET]
Definition: chan_mobile.c:134
#define MBL_CONFIG
Definition: chan_mobile.c:78
static int mbl_load_config(void)
Definition: chan_mobile.c:4624
static sdp_session_t * sdp_register(void)
Definition: chan_mobile.c:3119
void ast_smoother_reset(struct ast_smoother *s, int bytes)
Definition: smoother.c:79
enum mbl_type type
Definition: chan_mobile.c:124
#define LOG_NOTICE
Definition: logger.h:263
pthread_t monitor_thread
Definition: chan_mobile.c:138
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
ast_mutex_t lock
Definition: chan_mobile.c:121
struct ast_format_cap * capabilities
Definition: channel.h:633
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
int cw
Definition: chan_mobile.c:316
int signal
Definition: chan_mobile.c:335
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value)
Parse a CIEV event.
Definition: chan_mobile.c:2195
static int hfp_send_cusd(struct hfp_pvt *hfp, const char *code)
Send CUSD.
Definition: chan_mobile.c:2712
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
static int hfp_send_cnmi(struct hfp_pvt *hfp)
Setup SMS new message indication.
Definition: chan_mobile.c:2636
#define AST_MAX_CONTEXT
Definition: channel.h:136
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define HFP_CIND_CALLSETUP_INCOMING
Definition: chan_mobile.c:291
static struct hfp_ag * hfp_int2brsf(int brsf, struct hfp_ag *ag)
Convert a BRSF int to an hfp_ag struct.
Definition: chan_mobile.c:2490
static int hfp_send_chup(struct hfp_pvt *hfp)
Send AT+CHUP.
Definition: chan_mobile.c:2681
static char * handle_cli_mobile_rfcomm(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mobile.c:611
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:352
static int mbl_call(struct ast_channel *ast, const char *dest, int timeout)
Definition: chan_mobile.c:970
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
bdaddr_t addr
Definition: chan_mobile.c:103
int voice
Definition: chan_mobile.c:318
static int hfp_send_ecam(struct hfp_pvt *hfp)
Enable Sony Erricson extensions / indications.
Definition: chan_mobile.c:2182
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:843
#define HFP_CIND_CALLHELD
Definition: chan_mobile.c:280
static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode)
Set the SMS mode.
Definition: chan_mobile.c:2625
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_isphonenumber(const char *n)
Check if a string consists only of digits and + #.
Definition: callerid.c:998
static void * do_sco_listen(void *data)
Service new and existing SCO connections. This thread accepts new sco connections and handles audio d...
Definition: chan_mobile.c:4326
int errors
Definition: chan_mobile.c:324
#define HFP_HF_CONTROL
Definition: chan_mobile.c:263
unsigned int alignment_detection_triggered
Definition: chan_mobile.c:143
unsigned int outgoing_sms
Definition: chan_mobile.c:155
Definition: chan_mobile.c:460
int tag
Definition: chan_mobile.c:320
static int hsp_send_ok(int rsock)
Send an OK AT response.
Definition: chan_mobile.c:2924
int service
Definition: chan_mobile.c:331
static int sdp_search(char *addr, int profile)
Definition: chan_mobile.c:3071
#define HFP_AG_STATUS
Definition: chan_mobile.c:271
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
static at_message_t at_read_full(int rsock, char *buf, size_t count)
Read an AT message and clasify it.
Definition: chan_mobile.c:2017
Structure used to handle boolean flags.
Definition: utils.h:199
at_message_t
Definition: chan_mobile.c:419
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:245
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct timeval delivery
const char * usage
Definition: cli.h:177
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define HFP_HF_VOLUME
Definition: chan_mobile.c:261
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static int hfp_send_cmgr(struct hfp_pvt *hfp, int index)
Read an SMS message.
Definition: chan_mobile.c:2646
static int rfcomm_read_command(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of an AT command.
Definition: chan_mobile.c:1763
struct ast_frame ast_null_frame
Definition: main/frame.c:79
unsigned int incoming_sms
Definition: chan_mobile.c:156
struct hfp_ag brsf
Definition: chan_mobile.c:348
#define CLI_SUCCESS
Definition: cli.h:44
static int hfp_send_cmgs(struct hfp_pvt *hfp, const char *number)
Start sending an SMS message.
Definition: chan_mobile.c:2658
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
struct mbl_pvt::msg_queue msg_queue
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:124
unsigned int outgoing
Definition: chan_mobile.c:153
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
static int mbl_sendsms_exec(struct ast_channel *ast, const char *data)
Definition: chan_mobile.c:763
static ssize_t rfcomm_read(int rsock, char *buf, size_t count)
Read one Hayes AT message from an rfcomm socket.
Definition: chan_mobile.c:1808
#define abs(x)
Definition: f2c.h:195
Standard Command Line Interface.
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
static char * mblsendsms_desc
Definition: chan_mobile.c:211
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct adapter_pvt * adapter
Definition: chan_mobile.c:128
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
#define HFP_CIND_SERVICE
Definition: chan_mobile.c:277
char * cnum
Definition: chan_mobile.c:168
const char * ast_channel_name(const struct ast_channel *chan)
static void * do_discovery(void *data)
Definition: chan_mobile.c:4282
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
static void msg_queue_flush(struct mbl_pvt *pvt)
Remove all itmes from the queue and free them.
Definition: chan_mobile.c:3046
struct ast_smoother * bt_out_smoother
Definition: chan_mobile.c:135
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
static int handle_response_error(struct mbl_pvt *pvt, char *buf)
Handle ERROR AT messages.
Definition: chan_mobile.c:3442
static PGresult * result
Definition: cel_pgsql.c:88
static void set_unloading(void)
Set the unloading flag.
Definition: chan_mobile.c:4695
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text)
Parse a CMGR message.
Definition: chan_mobile.c:2352
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
static char * app_mblsendsms
Definition: chan_mobile.c:209
Options provided by main asterisk program.
This struct holds state information about the current hfp connection.
Definition: chan_mobile.c:344
Definition: search.h:40
int status
Definition: chan_mobile.c:322
int voice
Definition: chan_mobile.c:306
unsigned int needring
Definition: chan_mobile.c:159
static char * handle_cli_mobile_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_mobile.c:495
union ast_frame::@263 data
enum ast_frame_type frametype
int group
Definition: chan_mobile.c:126
static int rfcomm_read_and_expect_char(int rsock, char *result, char expected)
Read a character from the given stream and check if it matches what we expected.
Definition: chan_mobile.c:1520
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_channel_trylock(chan)
Definition: channel.h:2947
static char * mblstatus_desc
Definition: chan_mobile.c:203
int rport
Definition: chan_mobile.c:353
void * data
Definition: chan_mobile.c:463
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf)
Send an SMS message from the queue.
Definition: chan_mobile.c:3780
int ring_sched_id
Definition: chan_mobile.c:147
struct ast_format * format
static void * do_monitor_headset(void *data)
Definition: chan_mobile.c:4119
This struct holds HFP features the AG supports.
Definition: chan_mobile.c:315
unsigned int needcallerid
Definition: chan_mobile.c:157
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf)
Parse a CLIP event.
Definition: chan_mobile.c:2224
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define HFP_AG_TAG
Definition: chan_mobile.c:269
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
Asterisk module definitions.
struct ast_sched_context * sched
Definition: chan_mobile.c:149
static struct ast_channel_tech mbl_tech
Definition: chan_mobile.c:479
struct ast_frame fr
Definition: chan_mobile.c:120
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
static char * mblstatus_synopsis
Definition: chan_mobile.c:202
static int msg_queue_push_data(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to, void *data)
Add an item to the back of the queue with data.
Definition: chan_mobile.c:3004
#define HFP_CIND_CALLSETUP_NONE
Definition: chan_mobile.c:290
static struct ast_channel * mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_mobile.c:847
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
Structure for mutex and tracking information.
Definition: lock.h:135
static void rfcomm_append_buf(char **buf, size_t count, size_t *in_count, char c)
Append the given character to the given buffer and increase the in_count.
Definition: chan_mobile.c:1508
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1844
jack_status_t status
Definition: app_jack.c:146
#define HFP_CIND_CALLSETUP_OUTGOING
Definition: chan_mobile.c:292
static int unload_module(void)
Definition: chan_mobile.c:4702
Media Format Cache API.
#define ast_mutex_unlock(a)
Definition: lock.h:188
static int hfp_parse_cind(struct hfp_pvt *hfp, char *buf)
Read the result of the AT+CIND? command.
Definition: chan_mobile.c:2768
static char prefix[MAX_PREFIX]
Definition: http.c:141
#define AST_APP_ARG(name)
Define an application argument.
#define HFP_CIND_SERVICE_AVAILABLE
Definition: chan_mobile.c:297
static int mbl_has_service(struct mbl_pvt *pvt)
Check if a mobile device has service.
Definition: chan_mobile.c:1369
static struct test_val a
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:81