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>
78 #define MBL_CONFIG "chan_mobile.conf"
79 #define MBL_CONFIG_OLD "mobile.conf"
81 #define DEVICE_FRAME_SIZE 48
82 #define DEVICE_FRAME_FORMAT ast_format_slin
83 #define CHANNEL_FRAME_SIZE 320
85 static int discovery_interval = 60;
86 static pthread_t discovery_thread = AST_PTHREADT_NULL;
87 static sdp_session_t *sdp_session;
89 AST_MUTEX_DEFINE_STATIC(unload_mutex);
90 static int unloading_flag = 0;
104 unsigned int inuse:1;
105 unsigned int alignment_detection:1;
128 struct adapter_pvt *adapter;
133 char rfcomm_buf[256];
140 unsigned int no_callsetup:1;
141 unsigned int has_sms:1;
142 unsigned int do_alignment_detection:1;
143 unsigned int alignment_detection_triggered:1;
144 unsigned int blackberry:1;
145 short alignment_samples[4];
154 unsigned int incoming:1;
155 unsigned int outgoing_sms:1;
156 unsigned int incoming_sms:1;
157 unsigned int needcallerid:1;
158 unsigned int needchup:1;
159 unsigned int needring:1;
160 unsigned int answered:1;
161 unsigned int connected:1;
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"),
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";
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";
221 static int mbl_call(
struct ast_channel *ast,
const char *dest,
int timeout);
224 static int mbl_digit_end(
struct ast_channel *ast,
char digit,
unsigned int duration);
228 static int mbl_devicestate(
const char *
data);
230 static void do_alignment_detection(
struct mbl_pvt *pvt,
char *buf,
int buflen);
233 static int mbl_queue_hangup(
struct mbl_pvt *pvt);
234 static int mbl_ast_hangup(
struct mbl_pvt *pvt);
237 static int rfcomm_connect(bdaddr_t
src, bdaddr_t dst,
int remote_channel);
241 static ssize_t
rfcomm_read(
int rsock,
char *buf,
size_t count);
243 static int sco_connect(bdaddr_t
src, bdaddr_t dst);
244 static int sco_write(
int s,
char *buf,
int len);
246 static int sco_bind(
struct adapter_pvt *adapter);
249 static int sdp_search(
char *addr,
int profile);
251 static int headset_send_ring(
const void *
data);
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)
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)
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
286 #define HFP_CIND_CALL_NONE 0
287 #define HFP_CIND_CALL_ACTIVE 1
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
296 #define HFP_CIND_SERVICE_NONE 0
297 #define HFP_CIND_SERVICE_AVAILABLE 1
361 static struct hfp_hf hfp_our_brsf = {
372 static int hfp_parse_ciev(
struct hfp_pvt *hfp,
char *buf,
int *value);
374 static int parse_next_token(
char string[],
const int start,
const char delim);
376 static int hfp_parse_cmgr(
struct hfp_pvt *hfp,
char *buf,
char **from_number,
char **text);
390 static int hfp_send_vgs(
struct hfp_pvt *hfp,
int value);
393 static int hfp_send_vgm(
struct hfp_pvt *hfp,
int value);
404 static int hfp_send_cusd(
struct hfp_pvt *hfp,
const char *code);
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);
460 struct msg_queue_entry {
461 at_message_t expected;
462 at_message_t response_to;
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);
473 static struct msg_queue_entry *
msg_queue_head(
struct mbl_pvt *pvt);
481 .description =
"Bluetooth Mobile Device Channel Driver",
482 .requester = mbl_request,
484 .hangup = mbl_hangup,
485 .answer = mbl_answer,
486 .send_digit_end = mbl_digit_end,
490 .devicestate = mbl_devicestate
501 #define FORMAT1 "%-15.15s %-17.17s %-5.5s %-15.15s %-9.9s %-10.10s %-3.3s\n"
505 e->
command =
"mobile show devices";
507 "Usage: mobile show devices\n"
508 " Shows the state of Bluetooth Cell / Mobile devices.\n";
515 return CLI_SHOWUSAGE;
517 ast_cli(a->fd, FORMAT1,
"ID",
"Address",
"Group",
"Adapter",
"Connected",
"State",
"SMS");
519 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
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,
530 (pvt->has_sms) ?
"Yes" :
"No"
532 ast_mutex_unlock(&pvt->
lock);
543 struct adapter_pvt *adapter;
544 inquiry_info *ii = NULL;
545 int max_rsp, num_rsp;
547 int i, phport, hsport;
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"
558 "Usage: mobile search\n"
559 " Searches for Bluetooth Cell / Mobile devices in range.\n";
566 return CLI_SHOWUSAGE;
570 AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
577 ast_cli(a->fd,
"All Bluetooth adapters are in use at this time.\n");
583 flags = IREQ_CACHE_FLUSH;
585 ii =
ast_alloca(max_rsp *
sizeof(inquiry_info));
586 num_rsp = hci_inquiry(adapter->dev_id, len, max_rsp, NULL, &ii, flags);
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);
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);
596 hsport = sdp_search(addr, HEADSET_PROFILE_ID);
599 ast_cli(a->fd, FORMAT2, addr, name, (phport > 0 || hsport > 0) ?
"Yes" :
"No",
600 (phport > 0) ?
"Phone" :
"Headset", (phport > 0) ? phport : hsport);
603 ast_cli(a->fd,
"No Bluetooth Cell / Mobile devices found.\n");
614 struct mbl_pvt *pvt = NULL;
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";
629 return CLI_SHOWUSAGE;
632 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
633 if (!strcmp(pvt->id, a->argv[2]))
639 ast_cli(a->fd,
"Device %s not found.\n", a->argv[2]);
643 ast_mutex_lock(&pvt->
lock);
645 ast_cli(a->fd,
"Device %s not connected.\n", a->argv[2]);
649 snprintf(buf,
sizeof(buf),
"%s\r", a->argv[3]);
654 ast_mutex_unlock(&pvt->
lock);
662 struct mbl_pvt *pvt = NULL;
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";
677 return CLI_SHOWUSAGE;
680 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
681 if (!strcmp(pvt->id, a->argv[2]))
687 ast_cli(a->fd,
"Device %s not found.\n", a->argv[2]);
691 ast_mutex_lock(&pvt->
lock);
693 ast_cli(a->fd,
"Device %s not connected.\n", a->argv[2]);
697 snprintf(buf,
sizeof(buf),
"%s", a->argv[3]);
699 ast_cli(a->fd,
"[%s] error sending CUSD\n", pvt->id);
704 ast_mutex_unlock(&pvt->
lock);
715 static int mbl_status_exec(
struct ast_channel *ast,
const char *data)
728 if (ast_strlen_zero(data))
735 if (ast_strlen_zero(args.device) || ast_strlen_zero(args.variable))
741 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
742 if (!strcmp(pvt->id, args.device))
748 ast_mutex_lock(&pvt->
lock);
753 ast_mutex_unlock(&pvt->
lock);
756 snprintf(status,
sizeof(status),
"%d", stat);
763 static int mbl_sendsms_exec(
struct ast_channel *ast,
const char *data)
775 if (ast_strlen_zero(data))
782 if (ast_strlen_zero(args.device)) {
783 ast_log(LOG_ERROR,
"NULL device for message -- SMS will not be sent.\n");
787 if (ast_strlen_zero(args.dest)) {
788 ast_log(LOG_ERROR,
"NULL destination for message -- SMS will not be sent.\n");
792 if (ast_strlen_zero(args.message)) {
793 ast_log(LOG_ERROR,
"NULL Message to be sent -- SMS will not be sent.\n");
798 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
799 if (!strcmp(pvt->id, args.device))
805 ast_log(LOG_ERROR,
"Bluetooth device %s wasn't found in the list -- SMS will not be sent.\n", args.device);
809 ast_mutex_lock(&pvt->
lock);
811 ast_log(LOG_ERROR,
"Bluetooth device %s wasn't connected -- SMS will not be sent.\n", args.device);
816 ast_log(LOG_ERROR,
"Bluetooth device %s doesn't handle SMS -- SMS will not be sent.\n", args.device);
825 ast_log(LOG_ERROR,
"[%s] problem sending SMS message\n", pvt->id);
829 ast_mutex_unlock(&pvt->
lock);
836 ast_mutex_unlock(&pvt->
lock);
853 pvt->alignment_count = 0;
854 pvt->alignment_detection_triggered = 0;
855 if (pvt->adapter->alignment_detection)
856 pvt->do_alignment_detection = 1;
858 pvt->do_alignment_detection = 0;
860 ast_smoother_reset(pvt->bt_out_smoother, DEVICE_FRAME_SIZE);
861 ast_smoother_reset(pvt->bt_in_smoother, CHANNEL_FRAME_SIZE);
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);
873 ast_channel_tech_set(chn, &mbl_tech);
874 ast_channel_nativeformats_set(chn, mbl_tech.
capabilities);
875 ast_channel_set_rawreadformat(chn, DEVICE_FRAME_FORMAT);
876 ast_channel_set_rawwriteformat(chn, DEVICE_FRAME_FORMAT);
877 ast_channel_set_writeformat(chn, DEVICE_FRAME_FORMAT);
878 ast_channel_set_readformat(chn, DEVICE_FRAME_FORMAT);
879 ast_channel_tech_pvt_set(chn, pvt);
882 ast_channel_rings_set(chn, 1);
884 ast_channel_language_set(chn,
"en");
887 if (pvt->sco_socket != -1) {
890 ast_channel_unlock(chn);
904 char *dest_dev = NULL;
905 char *dest_num = NULL;
909 ast_log(LOG_WARNING,
"Channel requested with no data\n");
910 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
916 ast_log(LOG_WARNING,
"Asked to get a channel of unsupported format '%s'\n",
ast_format_cap_get_names(cap, &codec_buf));
917 *cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
923 dest_num = strchr(dest_dev,
'/');
927 if (((dest_dev[0] ==
'g') || (dest_dev[0] ==
'G')) && ((dest_dev[1] >=
'0') && (dest_dev[1] <=
'9'))) {
928 group = atoi(&dest_dev[1]);
933 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
934 if (group > -1 && pvt->group == group && pvt->
connected && !pvt->owner) {
940 }
else if (!strcmp(pvt->id, dest_dev)) {
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);
947 *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
951 if ((pvt->type == MBL_TYPE_PHONE) && !dest_num) {
952 ast_log(LOG_WARNING,
"Can't determine destination number.\n");
953 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
957 ast_mutex_lock(&pvt->
lock);
959 ast_mutex_unlock(&pvt->
lock);
961 ast_log(LOG_WARNING,
"Unable to allocate channel structure.\n");
962 *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
970 static int mbl_call(
struct ast_channel *ast,
const char *dest,
int timeout)
974 char *dest_num = NULL;
978 pvt = ast_channel_tech_pvt(ast);
980 if (pvt->type == MBL_TYPE_PHONE) {
981 dest_num = strchr(dest_dev,
'/');
983 ast_log(LOG_WARNING,
"Cant determine destination number.\n");
990 ast_log(LOG_WARNING,
"mbl_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
994 ast_debug(1,
"Calling %s on %s\n", dest, ast_channel_name(ast));
996 ast_mutex_lock(&pvt->
lock);
997 if (pvt->type == MBL_TYPE_PHONE) {
999 ast_mutex_unlock(&pvt->
lock);
1000 ast_log(LOG_ERROR,
"error sending ATD command on %s\n", pvt->id);
1003 pvt->hangupcause = 0;
1008 ast_log(LOG_ERROR,
"[%s] error ringing device\n", pvt->id);
1009 ast_mutex_unlock(&pvt->
lock);
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);
1022 ast_mutex_unlock(&pvt->
lock);
1031 struct mbl_pvt *pvt;
1033 if (!ast_channel_tech_pvt(ast)) {
1034 ast_log(LOG_WARNING,
"Asked to hangup channel not connected\n");
1037 pvt = ast_channel_tech_pvt(ast);
1039 ast_debug(1,
"[%s] hanging up device\n", pvt->id);
1041 ast_mutex_lock(&pvt->
lock);
1043 close(pvt->sco_socket);
1044 pvt->sco_socket = -1;
1056 ast_channel_tech_pvt_set(ast, NULL);
1058 ast_mutex_unlock(&pvt->
lock);
1069 struct mbl_pvt *pvt;
1071 pvt = ast_channel_tech_pvt(ast);
1073 if (pvt->type == MBL_TYPE_HEADSET)
1076 ast_mutex_lock(&pvt->
lock);
1082 ast_mutex_unlock(&pvt->
lock);
1088 static int mbl_digit_end(
struct ast_channel *ast,
char digit,
unsigned int duration)
1090 struct mbl_pvt *pvt = ast_channel_tech_pvt(ast);
1092 if (pvt->type == MBL_TYPE_HEADSET)
1095 ast_mutex_lock(&pvt->
lock);
1097 ast_mutex_unlock(&pvt->
lock);
1098 ast_debug(1,
"[%s] error sending digit %c\n", pvt->id, digit);
1102 ast_mutex_unlock(&pvt->
lock);
1104 ast_debug(1,
"[%s] dialed %c\n", pvt->id, digit);
1112 struct mbl_pvt *pvt = ast_channel_tech_pvt(ast);
1118 while (ast_mutex_trylock(&pvt->
lock)) {
1119 CHANNEL_DEADLOCK_AVOIDANCE(ast);
1122 if (!pvt->owner || pvt->sco_socket == -1) {
1126 memset(&pvt->fr, 0x00,
sizeof(
struct ast_frame));
1129 pvt->fr.
src =
"Mobile";
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;
1150 if (pvt->do_alignment_detection)
1151 do_alignment_detection(pvt, pvt->fr.
data.ptr, r);
1153 ast_smoother_feed(pvt->bt_in_smoother, &pvt->fr);
1154 fr = ast_smoother_read(pvt->bt_in_smoother);
1155 }
while (fr == NULL);
1158 ast_mutex_unlock(&pvt->
lock);
1163 ast_mutex_unlock(&pvt->
lock);
1170 struct mbl_pvt *pvt = ast_channel_tech_pvt(ast);
1179 while (ast_mutex_trylock(&pvt->
lock)) {
1180 CHANNEL_DEADLOCK_AVOIDANCE(ast);
1183 ast_smoother_feed(pvt->bt_out_smoother, frame);
1185 while ((f = ast_smoother_read(pvt->bt_out_smoother))) {
1186 sco_write(pvt->sco_socket, f->
data.ptr, f->
datalen);
1189 ast_mutex_unlock(&pvt->
lock);
1198 struct mbl_pvt *pvt = ast_channel_tech_pvt(newchan);
1201 ast_debug(1,
"fixup failed, no pvt on newchan\n");
1205 ast_mutex_lock(&pvt->
lock);
1206 if (pvt->owner == oldchan)
1207 pvt->owner = newchan;
1208 ast_mutex_unlock(&pvt->
lock);
1214 static int mbl_devicestate(
const char *data)
1219 struct mbl_pvt *pvt;
1223 ast_debug(1,
"Checking device state for device %s\n", device);
1226 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
1227 if (!strcmp(pvt->id, device))
1235 ast_mutex_lock(&pvt->
lock);
1245 ast_mutex_unlock(&pvt->
lock);
1281 static void do_alignment_detection(
struct mbl_pvt *pvt,
char *buf,
int buflen)
1288 if (pvt->alignment_detection_triggered) {
1289 for (i=buflen, p=buf+buflen-1; i>0; i--, p--)
1295 if (pvt->alignment_count < 4) {
1297 for (i=0, a=0; i<buflen/2; i++) {
1301 pvt->alignment_samples[pvt->alignment_count++] = a;
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]);
1307 a = abs(pvt->alignment_samples[1]) + abs(pvt->alignment_samples[2]) + abs(pvt->alignment_samples[3]);
1310 pvt->alignment_detection_triggered = 1;
1311 ast_debug(1,
"Alignment Detection Triggered.\n");
1313 pvt->do_alignment_detection = 0;
1321 if (ast_channel_trylock(pvt->owner)) {
1322 DEADLOCK_AVOIDANCE(&pvt->
lock);
1325 ast_channel_unlock(pvt->owner);
1334 static int mbl_queue_hangup(
struct mbl_pvt *pvt)
1338 if (ast_channel_trylock(pvt->owner)) {
1339 DEADLOCK_AVOIDANCE(&pvt->
lock);
1341 if (pvt->hangupcause != 0) {
1342 ast_channel_hangupcause_set(pvt->owner, pvt->hangupcause);
1345 ast_channel_unlock(pvt->owner);
1354 static int mbl_ast_hangup(
struct mbl_pvt *pvt)
1372 if (pvt->type != MBL_TYPE_PHONE)
1390 static int rfcomm_connect(bdaddr_t src, bdaddr_t dst,
int remote_channel)
1393 struct sockaddr_rc addr;
1396 if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
1397 ast_debug(1,
"socket() failed (%d).\n", errno);
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);
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);
1459 ast_debug(1,
"rfcomm_write() (%d) [%.*s]\n", rsock, (
int) count, buf);
1461 if ((out_count = write(rsock, p, count)) == -1) {
1462 ast_debug(1,
"rfcomm_write() error [%d]\n", errno);
1481 int exception, outfd;
1489 #ifdef RFCOMM_READ_DEBUG
1490 #define rfcomm_read_debug(c) __rfcomm_read_debug(c)
1491 static void __rfcomm_read_debug(
char c)
1501 #define rfcomm_read_debug(c)
1510 if (*in_count < count) {
1528 if ((res = read(rsock, result, 1)) < 1) {
1531 rfcomm_read_debug(*result);
1533 if (*result != expected) {
1569 while ((res = read(rsock, &c, 1)) == 1) {
1570 rfcomm_read_debug(c);
1574 }
else if (res == -2) {
1602 ast_log(LOG_ERROR,
"error parsing SMS prompt on rfcomm socket\n");
1715 ast_log(LOG_ERROR,
"error reading +CMGR message on rfcomm socket\n");
1736 }
else if (res != -2) {
1748 if (*in_count >= 5 && !strncmp(*buf - *in_count,
"+CMGR", 5)) {
1755 ast_log(LOG_ERROR,
"error parsing AT result on rfcomm socket\n");
1768 while ((res = read(rsock, &c, 1)) == 1) {
1769 rfcomm_read_debug(c);
1811 size_t in_count = 0;
1816 }
else if (res == -2) {
1833 static int sco_connect(bdaddr_t src, bdaddr_t dst)
1836 struct sockaddr_sco addr;
1839 if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
1840 ast_debug(1,
"socket() failed (%d).\n", errno);
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);
1857 memset(&addr, 0,
sizeof(addr));
1858 addr.sco_family = AF_BLUETOOTH;
1859 bacpy(&addr.sco_bdaddr, &dst);
1861 if (connect(s, (
struct sockaddr *)&addr,
sizeof(addr)) < 0) {
1862 ast_debug(1,
"sco connect() failed (%d).\n", errno);
1871 static int sco_write(
int s,
char *buf,
int len)
1877 ast_debug(3,
"sco_write() not ready\n");
1883 r = write(s, buf, len);
1885 ast_debug(3,
"sco write error %d\n", errno);
1900 struct adapter_pvt *adapter = (
struct adapter_pvt *) data;
1901 struct sockaddr_sco addr;
1903 struct mbl_pvt *pvt;
1906 struct sco_options so;
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);
1916 getsockopt(sock, SOL_SCO, SCO_OPTIONS, &so, &len);
1918 ba2str(&addr.sco_bdaddr, saddr);
1919 ast_debug(1,
"Incoming Audio Connection from device %s MTU is %d\n", saddr, so.mtu);
1924 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
1925 if (!bacmp(&pvt->addr, &addr.sco_bdaddr))
1930 ast_log(LOG_WARNING,
"could not find device for incoming audio connection\n");
1935 ast_mutex_lock(&pvt->
lock);
1936 if (pvt->sco_socket != -1) {
1937 close(pvt->sco_socket);
1938 pvt->sco_socket = -1;
1941 pvt->sco_socket = sock;
1945 ast_debug(1,
"incoming audio connection for pvt without owner\n");
1948 ast_mutex_unlock(&pvt->
lock);
1960 struct sockaddr_sco addr;
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);
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;
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;
1980 ast_log(LOG_ERROR,
"Unable to listen sco listener socket.\n");
1981 goto e_close_socket;
2005 return !strncmp(buf, prefix, strlen(prefix));
2024 if (!strcmp(
"OK", buf)) {
2026 }
else if (!strcmp(
"ERROR", buf)) {
2028 }
else if (!strcmp(
"RING", buf)) {
2030 }
else if (!strcmp(
"AT+CKPD=200", buf)) {
2032 }
else if (!strcmp(
"> ", buf)) {
2033 return AT_SMS_PROMPT;
2051 return AT_CMS_ERROR;
2061 return AT_NO_DIALTONE;
2063 return AT_NO_CARRIER;
2080 case AT_PARSE_ERROR:
2081 return "PARSE ERROR";
2083 return "READ ERROR";
2107 return "SMS PROMPT";
2109 return "+CMS ERROR";
2112 case AT_NO_DIALTONE:
2113 return "NO DIALTONE";
2115 return "NO CARRIER";
2172 if (!sscanf(buf,
"*ECAV: %2d,%2d,%2d", &ccid, &ccstatus, &calltype)) {
2173 ast_debug(1,
"[%s] error parsing ECAV event '%s'\n", hfp->
owner->id, buf);
2203 if (!sscanf(buf,
"+CIEV: %d,%d", &i, value)) {
2204 ast_debug(2,
"[%s] error parsing CIEV event '%s'\n", hfp->
owner->id, buf);
2205 return HFP_CIND_NONE;
2209 ast_debug(2,
"[%s] CIEV event index too high (%s)\n", hfp->
owner->id, buf);
2210 return HFP_CIND_NONE;
2233 struct cidinfo cidinfo = { NULL, NULL };
2238 ast_debug(3,
"[%s] hfp_parse_clip is processing \"%s\"\n", hfp->owner->id, buf);
2240 for (i = 1; i < ARRAY_LEN(tokens); i++) {
2244 ast_debug(3,
"[%s] hfp_parse_clip found tokens: 0=%s, 1=%s, 2=%s, 3=%s, 4=%s, 5=%s\n",
2245 hfp->owner->id, &buf[tokens[0]], &buf[tokens[1]], &buf[tokens[2]],
2246 &buf[tokens[3]], &buf[tokens[4]], &buf[tokens[5]]);
2251 ast_debug(1,
"[%s] hfp_parse_clip invalid cidinfo.cnum data \"%s\" - deleting\n",
2252 hfp->owner->id, cidinfo.cnum);
2260 cidinfo.cnam = &buf[tokens[5]];
2261 if (buf[tokens[5]] ==
'\0' && buf[tokens[4]] ==
'\0') {
2264 while (buf[i] ==
' ') {
2267 if (buf[i] ==
'"') {
2269 cidinfo.cnam = &buf[i];
2275 for (cnamtmp = cidinfo.cnam; *cnamtmp !=
'\0'; cnamtmp++) {
2276 if (!strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789-,abcdefghijklmnopqrstuvwxyz_", *cnamtmp)) {
2282 ast_debug(2,
"[%s] hfp_parse_clip replaced %d invalid byte(s) in cnam data\n",
2283 hfp->owner->id, invalid);
2285 ast_debug(2,
"[%s] hfp_parse_clip returns cnum=%s and cnam=%s\n",
2286 hfp->owner->id, cidinfo.cnum, cidinfo.cnam);
2304 for (index = start;
string[index] != 0; index++) {
2305 if ((
string[index] == delim) && !quoting ) {
2307 string[index] =
'\0';
2310 }
else if (
string[index] ==
'"' && !quoting) {
2313 }
else if (
string[index] ==
'"' ) {
2335 if (!sscanf(buf,
"+CMTI: %*[^,],%d", &index)) {
2336 ast_debug(2,
"[%s] error parsing CMTI event '%s'\n", hfp->
owner->id, buf);
2354 static int hfp_parse_cmgr(
struct hfp_pvt *hfp,
char *buf,
char **from_number,
char **text)
2365 for (i = 0; i < s && state != 6; i++) {
2368 if (buf[i] ==
',') {
2373 if (buf[i] ==
'"') {
2379 *from_number = &buf[i];
2384 if (buf[i] ==
'"') {
2390 if (buf[i] ==
'\n') {
2420 int i, message_start, message_end;
2432 for (i = 0; i < s; i++) {
2433 if (buf[i] ==
'"') {
2434 message_start = i + 1;
2439 if (message_start == 0 || message_start >= s) {
2444 for (i = s; i > 0; i--) {
2445 if (buf[i] ==
'"') {
2451 if (message_end == 0) {
2455 if (message_start >= message_end) {
2459 cusd = &buf[message_start];
2460 buf[message_end] =
'\0';
2474 brsf |= hf->
ecnr ? HFP_HF_ECNR : 0;
2475 brsf |= hf->
cw ? HFP_HF_CW : 0;
2476 brsf |= hf->
cid ? HFP_HF_CID : 0;
2477 brsf |= hf->
voice ? HFP_HF_VOICE : 0;
2478 brsf |= hf->
volume ? HFP_HF_VOLUME : 0;
2479 brsf |= hf->
status ? HFP_HF_STATUS : 0;
2480 brsf |= hf->
control ? HFP_HF_CONTROL : 0;
2494 ag->
cw = brsf & HFP_AG_CW ? 1 : 0;
2495 ag->
ecnr = brsf & HFP_AG_ECNR ? 1 : 0;
2496 ag->
voice = brsf & HFP_AG_VOICE ? 1 : 0;
2497 ag->
ring = brsf & HFP_AG_RING ? 1 : 0;
2498 ag->
tag = brsf & HFP_AG_TAG ? 1 : 0;
2499 ag->
reject = brsf & HFP_AG_REJECT ? 1 : 0;
2500 ag->
status = brsf & HFP_AG_STATUS ? 1 : 0;
2501 ag->
control = brsf & HFP_AG_CONTROL ? 1 : 0;
2502 ag->
errors = brsf & HFP_AG_ERRORS ? 1 : 0;
2519 snprintf(cmd,
sizeof(cmd),
"AT+BRSF=%d\r",
hfp_brsf2int(brsf));
2549 snprintf(cmd,
sizeof(cmd),
"AT+CMER=3,0,0,%d\r", status ? 1 : 0);
2561 snprintf(cmd,
sizeof(cmd),
"AT+VGS=%d\r", value);
2571 static int hfp_send_vgm(
struct hfp_pvt *hfp,
int value)
2574 snprintf(cmd,
sizeof(cmd),
"AT+VGM=%d\r", value);
2588 snprintf(cmd,
sizeof(cmd),
"AT+CLIP=%d\r", status ? 1 : 0);
2615 snprintf(cmd,
sizeof(cmd),
"AT+VTS=%c\r", digit);
2630 snprintf(cmd,
sizeof(cmd),
"AT+CMGF=%d\r", mode);
2651 snprintf(cmd,
sizeof(cmd),
"AT+CMGR=%d\r", index);
2663 snprintf(cmd,
sizeof(cmd),
"AT+CMGS=\"%s\"\r", number);
2675 snprintf(cmd,
sizeof(cmd),
"%.160s\x1a", message);
2696 snprintf(cmd,
sizeof(cmd),
"ATD%s;\r", number);
2717 snprintf(cmd,
sizeof(cmd),
"AT+CUSD=1,\"%s\",15\r", code);
2730 if (!sscanf(buf,
"+BRSF:%d", &brsf))
2750 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));
2754 if (!sscanf(indicator,
"%d", &value)) {
2755 ast_debug(1,
"error parsing CIND state '%s' for group %d\n", indicator, group);
2772 int i, state, group;
2774 char *indicator = NULL;
2783 for (i = 0; i < s; i++) {
2786 if (buf[i] ==
' ') {
2792 indicator = &buf[i];
2796 if (buf[i] ==
',') {
2822 int i, state, group;
2824 char *indicator = NULL;
2834 for (i = 0; i < s; i++) {
2837 if (buf[i] ==
'(') {
2843 if (buf[i] ==
'"') {
2848 indicator = &buf[i];
2852 if (buf[i] ==
'"') {
2858 if (buf[i] ==
'(') {
2866 if (buf[i] ==
')') {
2873 if (!strcmp(indicator,
"service")) {
2876 }
else if (!strcmp(indicator,
"call")) {
2879 }
else if (!strcmp(indicator,
"callsetup")) {
2883 }
else if (!strcmp(indicator,
"call_setup")) {
2887 }
else if (!strcmp(indicator,
"callheld")) {
2890 }
else if (!strcmp(indicator,
"signal")) {
2893 }
else if (!strcmp(indicator,
"roam")) {
2896 }
else if (!strcmp(indicator,
"battchg")) {
2901 ast_debug(2,
"ignoring unknown CIND indicator '%s'\n", indicator);
2904 ast_debug(1,
"can't store indicator %d (%s), we only support up to %d indicators", group, indicator, (
int)
sizeof(hfp->
cind_index));
2948 snprintf(cmd,
sizeof(cmd),
"\r\n+VGS=%d\r\n", gain);
2960 snprintf(cmd,
sizeof(cmd),
"\r\n+VGM=%d\r\n", gain);
2984 static int msg_queue_push(
struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
2986 struct msg_queue_entry *msg;
2990 msg->expected = expect;
2991 msg->response_to = response_to;
3006 static int msg_queue_push_data(
struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to,
void *data)
3008 struct msg_queue_entry *msg;
3012 msg->expected = expect;
3013 msg->response_to = response_to;
3036 struct msg_queue_entry *msg;
3039 ast_free(msg->data);
3050 struct msg_queue_entry *msg;
3073 static int sdp_search(
char *addr,
int profile)
3076 sdp_session_t *session = 0;
3079 uint32_t range = 0x0000ffff;
3080 sdp_list_t *response_list, *search_list, *attrid_list;
3082 sdp_list_t *proto_list;
3083 sdp_record_t *sdprec;
3085 str2ba(addr, &bdaddr);
3087 session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
3089 ast_debug(1,
"sdp_connect() failed on device %s.\n", addr);
3093 sdp_uuid32_create(&svc_uuid, profile);
3094 search_list = sdp_list_append(0, &svc_uuid);
3095 attrid_list = sdp_list_append(0, &range);
3096 response_list = 0x00;
3097 status = sdp_service_search_attr_req(session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
3099 if (response_list) {
3100 sdprec = (sdp_record_t *) response_list->data;
3102 if (sdp_get_access_protos(sdprec, &proto_list) == 0) {
3103 port = sdp_get_proto_port(proto_list, RFCOMM_UUID);
3104 sdp_list_free(proto_list, 0);
3106 sdp_record_free(sdprec);
3107 sdp_list_free(response_list, 0);
3109 ast_debug(1,
"No responses returned for device %s.\n", addr);
3111 ast_debug(1,
"sdp_service_search_attr_req() failed on device %s.\n", addr);
3113 sdp_list_free(search_list, 0);
3114 sdp_list_free(attrid_list, 0);
3121 static sdp_session_t *sdp_register(
void)
3123 uint32_t service_uuid_int[] = {0, 0, 0, GENERIC_AUDIO_SVCLASS_ID};
3124 uint8_t rfcomm_channel = 1;
3125 const char *service_name =
"Asterisk PABX";
3126 const char *service_dsc =
"Asterisk PABX";
3127 const char *service_prov =
"Asterisk";
3129 uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class1_uuid, svc_class2_uuid;
3130 sdp_list_t *l2cap_list = 0, *rfcomm_list = 0, *root_list = 0, *proto_list = 0, *access_proto_list = 0, *svc_uuid_list = 0;
3131 sdp_data_t *channel = 0;
3133 sdp_session_t *session = 0;
3135 sdp_record_t *record = sdp_record_alloc();
3137 sdp_uuid128_create(&svc_uuid, &service_uuid_int);
3138 sdp_set_service_id(record, svc_uuid);
3140 sdp_uuid32_create(&svc_class1_uuid, GENERIC_AUDIO_SVCLASS_ID);
3141 sdp_uuid32_create(&svc_class2_uuid, HEADSET_PROFILE_ID);
3143 svc_uuid_list = sdp_list_append(0, &svc_class1_uuid);
3144 svc_uuid_list = sdp_list_append(svc_uuid_list, &svc_class2_uuid);
3145 sdp_set_service_classes(record, svc_uuid_list);
3147 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
3148 root_list = sdp_list_append(0, &root_uuid);
3149 sdp_set_browse_groups( record, root_list );
3151 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
3152 l2cap_list = sdp_list_append(0, &l2cap_uuid);
3153 proto_list = sdp_list_append(0, l2cap_list);
3155 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
3156 channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
3157 rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
3158 sdp_list_append(rfcomm_list, channel);
3159 sdp_list_append(proto_list, rfcomm_list);
3161 access_proto_list = sdp_list_append(0, proto_list);
3162 sdp_set_access_protos(record, access_proto_list);
3164 sdp_set_info_attr(record, service_name, service_prov, service_dsc);
3166 if (!(session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY)))
3167 ast_log(LOG_WARNING,
"Failed to connect sdp and create session.\n");
3169 if (sdp_record_register(session, record, 0) < 0) {
3170 ast_log(LOG_WARNING,
"Failed to sdp_record_register error: %d\n", errno);
3175 sdp_data_free(channel);
3176 sdp_list_free(rfcomm_list, 0);
3177 sdp_list_free(root_list, 0);
3178 sdp_list_free(access_proto_list, 0);
3179 sdp_list_free(svc_uuid_list, 0);
3200 struct msg_queue_entry *entry;
3201 if ((entry =
msg_queue_head(pvt)) && entry->expected == AT_BRSF) {
3203 ast_debug(1,
"[%s] error parsing BRSF\n", pvt->id);
3208 ast_debug(1,
"[%s] error handling BRSF\n", pvt->id);
3214 ast_debug(1,
"[%s] received unexpected AT message 'BRSF' when expecting %s, ignoring\n", pvt->id,
at_msg2str(entry->expected));
3216 ast_debug(1,
"[%s] received unexpected AT message 'BRSF'\n", pvt->id);
3235 struct msg_queue_entry *entry;
3236 if ((entry =
msg_queue_head(pvt)) && entry->expected == AT_CIND) {
3237 switch (entry->response_to) {
3240 ast_debug(1,
"[%s] error performing CIND test\n", pvt->id);
3246 ast_debug(1,
"[%s] error getting CIND state\n", pvt->id);
3251 ast_debug(1,
"[%s] error getting CIND state\n", pvt->id);
3256 ast_debug(1,
"[%s] received unexpected AT message 'CIND' when expecting %s, ignoring\n", pvt->id,
at_msg2str(entry->expected));
3258 ast_debug(1,
"[%s] received unexpected AT message 'CIND'\n", pvt->id);
3277 struct msg_queue_entry *entry;
3279 switch (entry->response_to) {
3283 ast_debug(1,
"[%s] BSRF sent successfully\n", pvt->id);
3287 if (pvt->blackberry) {
3289 ast_debug(1,
"[%s] error sending CMER\n", pvt->id);
3294 ast_debug(1,
"[%s] error sending CIND test\n", pvt->id);
3300 ast_debug(1,
"[%s] CIND test sent successfully\n", pvt->id);
3307 ast_debug(1,
"[%s] error requesting CIND state\n", pvt->id);
3312 ast_debug(1,
"[%s] CIND sent successfully\n", pvt->id);
3316 ast_verb(3,
"Bluetooth Device %s has a call in progress - delaying connection.\n", pvt->id);
3322 if (!pvt->blackberry) {
3324 ast_debug(1,
"[%s] error sending CMER\n", pvt->id);
3329 ast_debug(1,
"[%s] error enabling calling line notification\n", pvt->id);
3335 ast_debug(1,
"[%s] CMER sent successfully\n", pvt->id);
3339 if (pvt->blackberry) {
3341 ast_debug(1,
"[%s] error sending CIND test\n", pvt->id);
3346 ast_debug(1,
"[%s] error enabling calling line notification\n", pvt->id);
3352 ast_debug(1,
"[%s] calling line indication enabled\n", pvt->id);
3354 ast_debug(1,
"[%s] error enabling Sony Ericsson call monitoring extensions\n", pvt->id);
3360 ast_debug(1,
"[%s] Sony Ericsson call monitoring is active on device\n", pvt->id);
3362 ast_debug(1,
"[%s] error synchronizing gain settings\n", pvt->id);
3368 ast_verb(3,
"Bluetooth Device %s initialized and ready.\n", pvt->id);
3372 ast_debug(1,
"[%s] volume level synchronization successful\n", pvt->id);
3377 ast_debug(1,
"[%s] error setting CMGF\n", pvt->id);
3383 ast_debug(1,
"[%s] sms text mode enabled\n", pvt->id);
3386 ast_debug(1,
"[%s] error setting CNMI\n", pvt->id);
3391 ast_debug(1,
"[%s] sms new message indication enabled\n", pvt->id);
3397 ast_debug(1,
"[%s] answer sent successfully\n", pvt->id);
3401 ast_debug(1,
"[%s] dial sent successfully\n", pvt->id);
3407 ast_debug(1,
"[%s] successful hangup\n", pvt->id);
3410 ast_debug(1,
"[%s] successfully sent sms message\n", pvt->id);
3414 ast_debug(1,
"[%s] digit sent successfully\n", pvt->id);
3417 ast_debug(1,
"[%s] CUSD code sent successfully\n", pvt->id);
3421 ast_debug(1,
"[%s] received OK for unhandled request: %s\n", pvt->id,
at_msg2str(entry->response_to));
3426 ast_debug(1,
"[%s] received AT message 'OK' when expecting %s, ignoring\n", pvt->id,
at_msg2str(entry->expected));
3428 ast_debug(1,
"[%s] received unexpected AT message 'OK'\n", pvt->id);
3446 struct msg_queue_entry *entry;
3448 && (entry->expected == AT_OK
3449 || entry->expected == AT_ERROR
3450 || entry->expected == AT_CMS_ERROR
3451 || entry->expected == AT_CMGR
3452 || entry->expected == AT_SMS_PROMPT)) {
3453 switch (entry->response_to) {
3457 ast_debug(1,
"[%s] error reading BSRF\n", pvt->id);
3460 ast_debug(1,
"[%s] error during CIND test\n", pvt->id);
3463 ast_debug(1,
"[%s] error requesting CIND state\n", pvt->id);
3466 ast_debug(1,
"[%s] error during CMER request\n", pvt->id);
3469 ast_debug(1,
"[%s] error enabling calling line indication\n", pvt->id);
3472 ast_debug(1,
"[%s] volume level synchronization failed\n", pvt->id);
3478 ast_debug(1,
"[%s] error setting CMGF\n", pvt->id);
3484 ast_debug(1,
"[%s] error setting CMGF\n", pvt->id);
3485 ast_debug(1,
"[%s] no SMS support\n", pvt->id);
3489 ast_debug(1,
"[%s] error setting CNMI\n", pvt->id);
3490 ast_debug(1,
"[%s] no SMS support\n", pvt->id);
3493 ast_debug(1,
"[%s] Mobile does not support Sony Ericsson extensions\n", pvt->id);
3498 ast_debug(1,
"[%s] error synchronizing gain settings\n", pvt->id);
3504 ast_verb(3,
"Bluetooth Device %s initialized and ready.\n", pvt->id);
3510 ast_debug(1,
"[%s] answer failed\n", pvt->id);
3511 mbl_queue_hangup(pvt);
3514 ast_debug(1,
"[%s] dial failed\n", pvt->id);
3519 ast_debug(1,
"[%s] error sending hangup, disconnecting\n", pvt->id);
3522 ast_debug(1,
"[%s] error reading sms message\n", pvt->id);
3526 ast_debug(1,
"[%s] error sending sms message\n", pvt->id);
3530 ast_debug(1,
"[%s] error sending digit\n", pvt->id);
3533 ast_verb(0,
"[%s] error sending CUSD command\n", pvt->id);
3537 ast_debug(1,
"[%s] received ERROR for unhandled request: %s\n", pvt->id,
at_msg2str(entry->response_to));
3542 ast_debug(1,
"[%s] received AT message 'ERROR' when expecting %s, ignoring\n", pvt->id,
at_msg2str(entry->expected));
3544 ast_debug(1,
"[%s] received unexpected AT message 'ERROR'\n", pvt->id);
3567 case HFP_CIND_CALL_NONE:
3568 ast_debug(1,
"[%s] line disconnected\n", pvt->id);
3570 ast_debug(1,
"[%s] hanging up owner\n", pvt->id);
3571 if (mbl_queue_hangup(pvt)) {
3572 ast_log(LOG_ERROR,
"[%s] error queueing hangup, disconnecting...\n", pvt->id);
3581 case HFP_CIND_CALL_ACTIVE:
3583 ast_debug(1,
"[%s] remote end answered\n", pvt->id);
3589 ast_verb(3,
"[%s] user answered bluetooth device from handset, disconnecting\n", pvt->id);
3590 mbl_queue_hangup(pvt);
3597 case HFP_CIND_CALLSETUP:
3599 case HFP_CIND_CALLSETUP_NONE:
3605 if (mbl_queue_hangup(pvt)) {
3606 ast_log(LOG_ERROR,
"[%s] error queueing hangup, disconnecting...\n", pvt->id);
3616 case HFP_CIND_CALLSETUP_INCOMING:
3617 ast_debug(1,
"[%s] incoming call, waiting for caller id\n", pvt->id);
3621 case HFP_CIND_CALLSETUP_OUTGOING:
3624 ast_debug(1,
"[%s] outgoing call\n", pvt->id);
3626 ast_verb(3,
"[%s] user dialed from handset, disconnecting\n", pvt->id);
3630 case HFP_CIND_CALLSETUP_ALERTING:
3632 ast_debug(1,
"[%s] remote alerting\n", pvt->id);
3640 ast_debug(1,
"[%s] error parsing CIND: %s\n", pvt->id, buf);
3655 struct msg_queue_entry *msg;
3657 struct cidinfo cidinfo;
3665 if (!(chan = mbl_new(
AST_STATE_RING, pvt, &cidinfo, NULL, NULL))) {
3666 ast_log(LOG_ERROR,
"[%s] unable to allocate channel for incoming call\n", pvt->id);
3677 ast_log(LOG_ERROR,
"[%s] unable to start pbx on incoming call\n", pvt->id);
3678 mbl_ast_hangup(pvt);
3696 ast_debug(1,
"[%s] got ring while waiting for caller id\n", pvt->id);
3714 ast_debug(1,
"[%s] incoming sms message\n", pvt->id);
3718 ast_debug(1,
"[%s] error sending CMGR to retrieve SMS message\n", pvt->id);
3725 ast_debug(1,
"[%s] error parsing incoming sms message alert, disconnecting\n", pvt->id);
3739 char *from_number = NULL, *text = NULL;
3741 struct msg_queue_entry *msg;
3747 ast_debug(1,
"[%s] error parsing sms message, disconnecting\n", pvt->id);
3751 ast_debug(1,
"[%s] successfully read sms message\n", pvt->id);
3756 ast_debug(1,
"[%s] error creating sms message channel, disconnecting\n", pvt->id);
3760 ast_channel_exten_set(chan,
"sms");
3765 ast_log(LOG_ERROR,
"[%s] unable to start pbx on incoming sms\n", pvt->id);
3766 mbl_ast_hangup(pvt);
3769 ast_debug(1,
"[%s] got unexpected +CMGR message, ignoring\n", pvt->id);
3784 struct msg_queue_entry *msg;
3786 ast_debug(1,
"[%s] error, got sms prompt with no pending sms messages\n", pvt->id);
3790 if (msg->expected != AT_SMS_PROMPT) {
3791 ast_debug(1,
"[%s] error, got sms prompt but no pending sms messages\n", pvt->id);
3798 ast_debug(1,
"[%s] error sending sms message\n", pvt->id);
3818 ast_verb(0,
"[%s] error parsing CUSD: %s\n", pvt->id, buf);
3822 ast_verb(0,
"[%s] CUSD response: %s\n", pvt->id, cusd);
3835 pvt->hangupcause = AST_CAUSE_USER_BUSY;
3850 ast_verb(1,
"[%s] mobile reports NO DIALTONE\n", pvt->id);
3865 ast_verb(1,
"[%s] mobile reports NO CARRIER\n", pvt->id);
3872 static void *do_monitor_phone(
void *data)
3874 struct mbl_pvt *pvt = (
struct mbl_pvt *)data;
3875 struct hfp_pvt *hfp = pvt->
hfp;
3878 at_message_t at_msg;
3879 struct msg_queue_entry *entry;
3888 ast_mutex_lock(&pvt->
lock);
3894 ast_mutex_unlock(&pvt->
lock);
3897 ast_mutex_lock(&pvt->
lock);
3899 ast_mutex_unlock(&pvt->
lock);
3902 ast_debug(1,
"[%s] timeout waiting for rfcomm data, disconnecting\n", pvt->id);
3903 ast_mutex_lock(&pvt->
lock);
3906 switch (entry->response_to) {
3908 if (pvt->blackberry)
3911 ast_debug(1,
"[%s] timeout during CIND test, try setting 'blackberry=yes'\n", hfp->
owner->id);
3914 if (pvt->blackberry)
3915 ast_debug(1,
"[%s] timeout after sending CMER, try setting 'blackberry=no'\n", hfp->
owner->id);
3917 ast_debug(1,
"[%s] timeout after sending CMER\n", hfp->
owner->id);
3920 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));
3925 ast_mutex_unlock(&pvt->
lock);
3930 ast_debug(1,
"[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
3934 ast_debug(1,
"[%s] read %s\n", pvt->id, buf);
3938 ast_mutex_lock(&pvt->
lock);
3940 ast_mutex_unlock(&pvt->
lock);
3943 ast_mutex_unlock(&pvt->
lock);
3946 ast_mutex_lock(&pvt->
lock);
3948 ast_mutex_unlock(&pvt->
lock);
3951 ast_mutex_unlock(&pvt->
lock);
3954 ast_mutex_lock(&pvt->
lock);
3956 ast_mutex_unlock(&pvt->
lock);
3959 ast_mutex_unlock(&pvt->
lock);
3963 ast_mutex_lock(&pvt->
lock);
3965 ast_mutex_unlock(&pvt->
lock);
3968 ast_mutex_unlock(&pvt->
lock);
3971 ast_mutex_lock(&pvt->
lock);
3973 ast_mutex_unlock(&pvt->
lock);
3976 ast_mutex_unlock(&pvt->
lock);
3979 ast_mutex_lock(&pvt->
lock);
3981 ast_mutex_unlock(&pvt->
lock);
3984 ast_mutex_unlock(&pvt->
lock);
3987 ast_mutex_lock(&pvt->
lock);
3989 ast_mutex_unlock(&pvt->
lock);
3992 ast_mutex_unlock(&pvt->
lock);
3995 ast_mutex_lock(&pvt->
lock);
3997 ast_mutex_unlock(&pvt->
lock);
4000 ast_mutex_unlock(&pvt->
lock);
4003 ast_mutex_lock(&pvt->
lock);
4005 ast_mutex_unlock(&pvt->
lock);
4008 ast_mutex_unlock(&pvt->
lock);
4011 ast_mutex_lock(&pvt->
lock);
4013 ast_mutex_unlock(&pvt->
lock);
4016 ast_mutex_unlock(&pvt->
lock);
4019 ast_mutex_lock(&pvt->
lock);
4021 ast_mutex_unlock(&pvt->
lock);
4024 ast_mutex_unlock(&pvt->
lock);
4027 ast_mutex_lock(&pvt->
lock);
4029 ast_mutex_unlock(&pvt->
lock);
4032 ast_mutex_unlock(&pvt->
lock);
4034 case AT_NO_DIALTONE:
4035 ast_mutex_lock(&pvt->
lock);
4037 ast_mutex_unlock(&pvt->
lock);
4040 ast_mutex_unlock(&pvt->
lock);
4043 ast_mutex_lock(&pvt->
lock);
4045 ast_mutex_unlock(&pvt->
lock);
4048 ast_mutex_unlock(&pvt->
lock);
4051 ast_mutex_lock(&pvt->
lock);
4054 ast_mutex_unlock(&pvt->
lock);
4058 ast_mutex_unlock(&pvt->
lock);
4061 ast_debug(1,
"[%s] ignoring unknown message: %s\n", pvt->id, buf);
4063 case AT_PARSE_ERROR:
4064 ast_debug(1,
"[%s] error parsing message\n", pvt->id);
4067 ast_debug(1,
"[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
4077 ast_verb(3,
"Error initializing Bluetooth device %s.\n", pvt->id);
4079 ast_mutex_lock(&pvt->
lock);
4081 ast_debug(1,
"[%s] device disconnected, hanging up owner\n", pvt->id);
4083 mbl_queue_hangup(pvt);
4086 close(pvt->rfcomm_socket);
4087 close(pvt->sco_socket);
4088 pvt->sco_socket = -1;
4095 pvt->adapter->inuse = 0;
4096 ast_mutex_unlock(&pvt->
lock);
4098 ast_verb(3,
"Bluetooth Device %s has disconnected.\n", pvt->id);
4099 manager_event(EVENT_FLAG_SYSTEM,
"MobileStatus",
"Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
4104 static int headset_send_ring(
const void *data)
4106 struct mbl_pvt *pvt = (
struct mbl_pvt *) data;
4107 ast_mutex_lock(&pvt->
lock);
4109 ast_mutex_unlock(&pvt->
lock);
4112 ast_mutex_unlock(&pvt->
lock);
4115 ast_debug(1,
"[%s] error sending RING\n", pvt->id);
4121 static void *do_monitor_headset(
void *data)
4124 struct mbl_pvt *pvt = (
struct mbl_pvt *)data;
4127 at_message_t at_msg;
4130 ast_verb(3,
"Bluetooth Device %s initialised and ready.\n", pvt->id);
4144 if ((at_msg =
at_read_full(pvt->rfcomm_socket, buf,
sizeof(buf))) < 0) {
4145 ast_debug(1,
"[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
4148 ast_debug(1,
"[%s] %s\n", pvt->id, buf);
4156 ast_debug(1,
"[%s] error sending AT message 'OK'\n", pvt->id);
4161 ast_mutex_lock(&pvt->
lock);
4168 mbl_queue_hangup(pvt);
4172 if ((pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr)) == -1) {
4173 ast_log(LOG_ERROR,
"[%s] unable to create audio connection\n", pvt->id);
4174 mbl_queue_hangup(pvt);
4175 ast_mutex_unlock(&pvt->
lock);
4185 ast_debug(1,
"[%s] error sending VGS/VGM\n", pvt->id);
4186 mbl_queue_hangup(pvt);
4187 ast_mutex_unlock(&pvt->
lock);
4194 mbl_queue_hangup(pvt);
4199 if ((pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr)) == -1) {
4200 ast_log(LOG_ERROR,
"[%s] unable to create audio connection\n", pvt->id);
4201 ast_mutex_unlock(&pvt->
lock);
4207 if (!(chan = mbl_new(
AST_STATE_UP, pvt, NULL, NULL, NULL))) {
4208 ast_log(LOG_ERROR,
"[%s] unable to allocate channel for incoming call\n", pvt->id);
4209 ast_mutex_unlock(&pvt->
lock);
4215 ast_channel_exten_set(chan,
"s");
4217 ast_log(LOG_ERROR,
"[%s] unable to start pbx on incoming call\n", pvt->id);
4219 ast_mutex_unlock(&pvt->
lock);
4223 ast_mutex_unlock(&pvt->
lock);
4226 ast_debug(1,
"[%s] received unknown AT command: %s (%s)\n", pvt->id, buf,
at_msg2str(at_msg));
4228 ast_debug(1,
"[%s] error sending AT message 'ERROR'\n", pvt->id);
4236 ast_mutex_lock(&pvt->
lock);
4238 ast_debug(1,
"[%s] device disconnected, hanging up owner\n", pvt->id);
4239 mbl_queue_hangup(pvt);
4243 close(pvt->rfcomm_socket);
4244 close(pvt->sco_socket);
4245 pvt->sco_socket = -1;
4253 pvt->adapter->inuse = 0;
4254 ast_mutex_unlock(&pvt->
lock);
4256 manager_event(EVENT_FLAG_SYSTEM,
"MobileStatus",
"Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
4257 ast_verb(3,
"Bluetooth Device %s has disconnected\n", pvt->id);
4263 static int start_monitor(
struct mbl_pvt *pvt)
4266 if (pvt->type == MBL_TYPE_PHONE) {
4267 pvt->
hfp->
rsock = pvt->rfcomm_socket;
4269 if (ast_pthread_create_background(&pvt->monitor_thread, NULL, do_monitor_phone, pvt) < 0) {
4270 pvt->monitor_thread = AST_PTHREADT_NULL;
4274 if (ast_pthread_create_background(&pvt->monitor_thread, NULL, do_monitor_headset, pvt) < 0) {
4275 pvt->monitor_thread = AST_PTHREADT_NULL;
4284 static void *do_discovery(
void *data)
4287 struct adapter_pvt *adapter;
4288 struct mbl_pvt *pvt;
4292 AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4293 if (!adapter->inuse) {
4295 AST_RWLIST_TRAVERSE(&
devices, pvt, entry) {
4296 ast_mutex_lock(&pvt->
lock);
4297 if (!adapter->inuse && !pvt->
connected && !strcmp(adapter->id, pvt->adapter->id)) {
4298 if ((pvt->rfcomm_socket = rfcomm_connect(adapter->addr, pvt->addr, pvt->rfcomm_port)) > -1) {
4299 if (start_monitor(pvt)) {
4302 manager_event(EVENT_FLAG_SYSTEM,
"MobileStatus",
"Status: Connect\r\nDevice: %s\r\n", pvt->id);
4303 ast_verb(3,
"Bluetooth Device %s has connected, initializing...\n", pvt->id);
4307 ast_mutex_unlock(&pvt->
lock);
4317 sleep(discovery_interval);
4330 struct adapter_pvt *adapter = (
struct adapter_pvt *) data;
4336 ast_log(LOG_ERROR,
"ast_io_wait() failed for adapter %s\n", adapter->id);
4342 ast_log(LOG_ERROR,
"ast_io_wait() failed for audio on adapter %s\n", adapter->id);
4369 struct adapter_pvt *adapter;
4371 struct hci_dev_req dr;
4374 id = ast_variable_retrieve(cfg, cat,
"id");
4375 address = ast_variable_retrieve(cfg, cat,
"address");
4377 if (ast_strlen_zero(
id) || ast_strlen_zero(address)) {
4378 ast_log(LOG_ERROR,
"Skipping adapter. Missing id or address settings.\n");
4382 ast_debug(1,
"Reading configuration for adapter %s %s.\n",
id, address);
4384 if (!(adapter =
ast_calloc(1,
sizeof(*adapter)))) {
4385 ast_log(LOG_ERROR,
"Skipping adapter %s. Error allocating memory.\n",
id);
4390 str2ba(address, &adapter->addr);
4393 adapter->dev_id = hci_devid(address);
4394 adapter->hci_socket = hci_open_dev(adapter->dev_id);
4395 if (adapter->dev_id < 0 || adapter->hci_socket < 0) {
4396 ast_log(LOG_ERROR,
"Skipping adapter %s. Unable to communicate with adapter.\n", adapter->id);
4397 goto e_free_adapter;
4401 hci_read_voice_setting(adapter->hci_socket, &vs, 1000);
4404 ast_log(LOG_ERROR,
"Skipping adapter %s. Voice setting must be 0x0060 - see 'man hciconfig' for details.\n", adapter->id);
4405 goto e_hci_close_dev;
4408 for (v = ast_variable_browse(cfg, cat); v; v = v->
next) {
4409 if (!strcasecmp(v->
name,
"forcemaster")) {
4411 dr.dev_id = adapter->dev_id;
4412 if (hci_strtolm(
"master", &dr.dev_opt)) {
4413 if (ioctl(adapter->hci_socket, HCISETLINKMODE, (
unsigned long) &dr) < 0) {
4414 ast_log(LOG_WARNING,
"Unable to set adapter %s link mode to MASTER. Ignoring 'forcemaster' option.\n", adapter->id);
4418 }
else if (!strcasecmp(v->
name,
"alignmentdetection")) {
4425 ast_log(LOG_ERROR,
"Unable to create I/O context for audio connection listener\n");
4426 goto e_hci_close_dev;
4430 ast_log(LOG_ERROR,
"Unable to create I/O context for audio connections\n");
4431 goto e_destroy_accept_io;
4436 ast_log(LOG_ERROR,
"Skipping adapter %s. Error binding audio connection listener socket.\n", adapter->id);
4442 ast_log(LOG_ERROR,
"Skipping adapter %s. Error adding listener socket to I/O context.\n", adapter->id);
4448 ast_log(LOG_ERROR,
"Skipping adapter %s. Error creating audio connection listener thread.\n", adapter->id);
4454 AST_RWLIST_INSERT_HEAD(&adapters, adapter, entry);
4456 ast_debug(1,
"Loaded adapter %s %s.\n", adapter->id, address);
4466 e_destroy_accept_io:
4469 hci_close_dev(adapter->hci_socket);
4484 struct mbl_pvt *pvt;
4485 struct adapter_pvt *adapter;
4487 const char *
address, *adapter_str, *port;
4488 ast_debug(1,
"Reading configuration for device %s.\n", cat);
4490 adapter_str = ast_variable_retrieve(cfg, cat,
"adapter");
4491 if(ast_strlen_zero(adapter_str)) {
4492 ast_log(LOG_ERROR,
"Skipping device %s. No adapter specified.\n", cat);
4498 AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4499 if (!strcmp(adapter->id, adapter_str))
4504 ast_log(LOG_ERROR,
"Skipping device %s. Unknown adapter '%s' specified.\n", cat, adapter_str);
4508 address = ast_variable_retrieve(cfg, cat,
"address");
4509 port = ast_variable_retrieve(cfg, cat,
"port");
4510 if (ast_strlen_zero(port) || ast_strlen_zero(address)) {
4511 ast_log(LOG_ERROR,
"Skipping device %s. Missing required port or address setting.\n", cat);
4517 ast_log(LOG_ERROR,
"Skipping device %s. Error allocating memory.\n", cat);
4521 ast_mutex_init(&pvt->
lock);
4526 pvt->type = MBL_TYPE_PHONE;
4530 pvt->adapter = adapter;
4532 str2ba(address, &pvt->addr);
4534 pvt->rfcomm_socket = -1;
4535 pvt->rfcomm_port = atoi(port);
4536 pvt->sco_socket = -1;
4537 pvt->monitor_thread = AST_PTHREADT_NULL;
4538 pvt->ring_sched_id = -1;
4542 if (!(pvt->bt_out_smoother = ast_smoother_new(DEVICE_FRAME_SIZE))) {
4543 ast_log(LOG_ERROR,
"Skipping device %s. Error setting up frame bt_out_smoother.\n", cat);
4548 if (!(pvt->bt_in_smoother = ast_smoother_new(CHANNEL_FRAME_SIZE))) {
4549 ast_log(LOG_ERROR,
"Skipping device %s. Error setting up frame bt_in_smoother.\n", cat);
4550 goto e_free_bt_out_smoother;
4555 ast_log(LOG_ERROR,
"Skipping device %s. Error setting up dsp for dtmf detection.\n", cat);
4556 goto e_free_bt_in_smoother;
4561 ast_log(LOG_ERROR,
"Unable to create scheduler context for headset device\n");
4568 for (v = ast_variable_browse(cfg, cat); v; v = v->
next) {
4569 if (!strcasecmp(v->
name,
"type")) {
4570 if (!strcasecmp(v->
value,
"headset"))
4571 pvt->type = MBL_TYPE_HEADSET;
4573 pvt->type = MBL_TYPE_PHONE;
4574 }
else if (!strcasecmp(v->
name,
"context")) {
4576 }
else if (!strcasecmp(v->
name,
"group")) {
4578 pvt->group = atoi(v->
value);
4579 }
else if (!strcasecmp(v->
name,
"sms")) {
4581 }
else if (!strcasecmp(v->
name,
"nocallsetup")) {
4584 if (pvt->no_callsetup)
4585 ast_debug(1,
"Setting nocallsetup mode for device %s.\n", pvt->id);
4586 }
else if (!strcasecmp(v->
name,
"blackberry")) {
4592 if (pvt->type == MBL_TYPE_PHONE) {
4594 ast_log(LOG_ERROR,
"Skipping device %s. Error allocating memory.\n", pvt->id);
4599 pvt->
hfp->
rport = pvt->rfcomm_port;
4606 AST_RWLIST_INSERT_HEAD(&
devices, pvt, entry);
4608 ast_debug(1,
"Loaded device %s.\n", pvt->id);
4615 ast_dsp_free(pvt->dsp);
4616 e_free_bt_in_smoother:
4617 ast_smoother_free(pvt->bt_in_smoother);
4618 e_free_bt_out_smoother:
4619 ast_smoother_free(pvt->bt_out_smoother);
4626 static int mbl_load_config(
void)
4641 for (v = ast_variable_browse(cfg,
"general"); v; v = v->
next) {
4642 if (!strcasecmp(v->
name,
"interval")) {
4643 if (!sscanf(v->
value,
"%d", &discovery_interval)) {
4644 ast_log(LOG_NOTICE,
"error parsing 'interval' in general section, using default value\n");
4651 if (!strcasecmp(cat,
"adapter")) {
4656 if (AST_RWLIST_EMPTY(&adapters)) {
4658 "***********************************************************************\n"
4659 "No adapters could be loaded from the configuration file.\n"
4660 "Please review mobile.conf. See sample for details.\n"
4661 "***********************************************************************\n"
4669 if (strcasecmp(cat,
"general") && strcasecmp(cat,
"adapter")) {
4687 ast_mutex_lock(&unload_mutex);
4688 res = unloading_flag;
4689 ast_mutex_unlock(&unload_mutex);
4699 ast_mutex_lock(&unload_mutex);
4701 ast_mutex_unlock(&unload_mutex);
4704 static int unload_module(
void)
4706 struct mbl_pvt *pvt;
4707 struct adapter_pvt *adapter;
4721 if (discovery_thread != AST_PTHREADT_NULL) {
4722 pthread_kill(discovery_thread, SIGURG);
4723 pthread_join(discovery_thread, NULL);
4728 AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4736 while ((pvt = AST_RWLIST_REMOVE_HEAD(&
devices, entry))) {
4737 if (pvt->monitor_thread != AST_PTHREADT_NULL) {
4738 pthread_kill(pvt->monitor_thread, SIGURG);
4739 pthread_join(pvt->monitor_thread, NULL);
4742 close(pvt->sco_socket);
4743 close(pvt->rfcomm_socket);
4751 ast_smoother_free(pvt->bt_out_smoother);
4752 ast_smoother_free(pvt->bt_in_smoother);
4753 ast_dsp_free(pvt->dsp);
4761 while ((adapter = AST_RWLIST_REMOVE_HEAD(&adapters, entry))) {
4765 hci_close_dev(adapter->hci_socket);
4771 sdp_close(sdp_session);
4778 static int load_module(
void)
4789 dev_id = hci_get_route(NULL);
4791 s = hci_open_dev(dev_id);
4792 if (dev_id < 0 || s < 0) {
4793 ast_log(LOG_ERROR,
"No Bluetooth devices found. Not loading module.\n");
4802 if (mbl_load_config()) {
4803 ast_log(LOG_ERROR,
"Errors reading config file %s. Not loading module.\n", MBL_CONFIG);
4809 sdp_session = sdp_register();
4812 if (ast_pthread_create_background(&discovery_thread, NULL, do_discovery, NULL) < 0) {
4813 ast_log(LOG_ERROR,
"Unable to create discovery thread.\n");
4819 ast_log(LOG_ERROR,
"Unable to register channel class %s\n",
"Mobile");
4835 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"Bluetooth Mobile Device Channel Driver",
4836 .support_level = AST_MODULE_SUPPORT_EXTENDED,
4837 .load = load_module,
4838 .unload = unload_module,
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
struct ast_variable * next
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
static int handle_response_busy(struct mbl_pvt *pvt)
Handle BUSY messages.
static int handle_response_cind(struct mbl_pvt *pvt, char *buf)
Handle the CIND response.
static int rfcomm_read_until_ok(int rsock, char **buf, size_t count, size_t *in_count)
Read until a.
static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
Handle AT+CIEV messages.
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...
Main Channel structure associated with a channel.
static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf)
Handle NO CARRIER messages.
static int hfp_send_dtmf(struct hfp_pvt *hfp, char digit)
Send a DTMF command.
static int hfp_send_atd(struct hfp_pvt *hfp, const char *number)
Send ATD.
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.
static int rfcomm_read_result(int rsock, char **buf, size_t count, size_t *in_count)
Read and AT result code.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
static int rfcomm_wait(int rsock, int *ms)
Wait for activity on an rfcomm socket.
static char * hfp_parse_cusd(struct hfp_pvt *hfp, char *buf)
Parse a CUSD answer.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static struct mbl_pvt * mbl_load_device(struct ast_config *cfg, const char *cat)
Load a device from the configuration file.
#define DSP_DIGITMODE_DTMF
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Convenient Signal Processing routines.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' 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.
struct io_context * accept_io
static int handle_response_brsf(struct mbl_pvt *pvt, char *buf)
Handle the BRSF response.
descriptor for a cli entry.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
pthread_t sco_listener_thread
static int check_unloading(void)
Check if the module is unloading.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf)
Parse BRSF data.
Structure for variables, used for configurations and for channel variables.
static int hsp_send_vgs(int rsock, int gain)
Send a speaker gain unsolicited AT response.
static int hfp_send_cind(struct hfp_pvt *hfp)
Send the CIND read command.
static struct ast_sockaddr address
Address for UDPTL.
static int handle_response_cmti(struct mbl_pvt *pvt, char *buf)
Handle AT+CMTI messages.
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Structure to pass both assignedid values to channel drivers.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
ast_channel_state
ast_channel states
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
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.
static int rfcomm_write_full(int rsock, char *buf, size_t count)
Write to an rfcomm socket.
static int hfp_send_ata(struct hfp_pvt *hfp)
Send ATA.
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 ...
#define ast_strdup(str)
A wrapper for strdup()
static int hfp_send_sms_text(struct hfp_pvt *hfp, const char *message)
Send the text of an SMS message.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
I/O Management (derived from Cheops-NG)
static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf)
Handle NO DIALTONE messages.
static int hsp_send_error(int rsock)
Send an ERROR AT response.
static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf)
Handle AT+CMGR messages.
int ast_unregister_application(const char *app)
Unregister an application.
static int at_match_prefix(char *buf, char *prefix)
Match the given buffer with the given prefix.
Asterisk internal frame definitions.
static int sco_bind(struct adapter_pvt *adapter)
Bind an SCO listener socket for the given adapter.
struct ast_frame_subclass subclass
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.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf)
Parse a CMTI notification.
static int hfp_parse_cind_indicator(struct hfp_pvt *hfp, int group, char *indicator)
Parse and store the given indicator.
static struct adapter_pvt * mbl_load_adapter(struct ast_config *cfg, const char *cat)
Load an adapter from the configuration file.
Configuration File Parser.
#define DSP_DIGITMODE_RELAXDTMF
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
static int hfp_send_clip(struct hfp_pvt *hfp, int status)
Enable or disable calling line identification.
static int handle_response_cusd(struct mbl_pvt *pvt, char *buf)
Handle CUSD messages.
#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...
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
General Asterisk PBX channel definitions.
static pthread_t monitor_thread
This is the thread for the monitor which checks for input on the channels which are not currently in ...
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
void io_context_destroy(struct io_context *ioc)
Destroys a context.
static int hfp_send_vgs(struct hfp_pvt *hfp, int value)
Send the current speaker gain level.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static int handle_response_clip(struct mbl_pvt *pvt, char *buf)
Handle AT+CLIP messages.
static int hsp_send_vgm(int rsock, int gain)
Send a microphone gain unsolicited AT response.
#define ast_register_application(app, execute, synopsis, description)
Register an application.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Global IO variables are now in a struct in order to be made threadsafe.
static int hfp_send_brsf(struct hfp_pvt *hfp, struct hfp_hf *brsf)
Send a BRSF request.
static int handle_response_ring(struct mbl_pvt *pvt, char *buf)
Handle RING messages.
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
static int hfp_brsf2int(struct hfp_hf *hf)
Convert a hfp_hf struct to a BRSF int.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
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...
static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
Parse a ECAV event.
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.
This struct holds mappings for indications.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
static int handle_response_ok(struct mbl_pvt *pvt, char *buf)
Handle OK AT messages.
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.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
This struct holds HFP features that we support.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
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.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
static int rfcomm_read_cmgr(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of a +CMGR message.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static int hfp_send_cind_test(struct hfp_pvt *hfp)
Send the CIND test command.
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".
Support for dynamic strings.
static int rfcomm_read_until_crlf(int rsock, char **buf, size_t count, size_t *in_count)
Read until.
static int hsp_send_ring(int rsock)
Send a RING unsolicited AT response.
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
struct ast_format_cap * capabilities
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value)
Parse a CIEV event.
static int hfp_send_cusd(struct hfp_pvt *hfp, const char *code)
Send CUSD.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
static int hfp_send_cnmi(struct hfp_pvt *hfp)
Setup SMS new message indication.
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
static struct hfp_ag * hfp_int2brsf(int brsf, struct hfp_ag *ag)
Convert a BRSF int to an hfp_ag struct.
static int hfp_send_chup(struct hfp_pvt *hfp)
Send AT+CHUP.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
static int hfp_send_ecam(struct hfp_pvt *hfp)
Enable Sony Ericsson extensions / indications.
Support for logging to various files, console and syslog Configuration in file logger.conf.
static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode)
Set the SMS mode.
Module has failed to load, may be in an inconsistent state.
int ast_isphonenumber(const char *n)
Check if a string consists only of digits and + #.
static void * do_sco_listen(void *data)
Service new and existing SCO connections. This thread accepts new sco connections and handles audio d...
unsigned int outgoing_sms
static int hsp_send_ok(int rsock)
Send an OK AT response.
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.
static at_message_t at_read_full(int rsock, char *buf, size_t count)
Read an AT message and classify it.
Structure used to handle boolean flags.
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
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.
static int rfcomm_read_command(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of an AT command.
struct ast_frame ast_null_frame
unsigned int incoming_sms
static int hfp_send_cmgs(struct hfp_pvt *hfp, const char *number)
Start sending an SMS message.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
static ssize_t rfcomm_read(int rsock, char *buf, size_t count)
Read one Hayes AT message from an rfcomm socket.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
static void msg_queue_flush(struct mbl_pvt *pvt)
Remove all items from the queue and free them.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
static int handle_response_error(struct mbl_pvt *pvt, char *buf)
Handle ERROR AT messages.
static void set_unloading(void)
Set the unloading flag.
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
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.
static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text)
Parse a CMGR message.
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
Options provided by main asterisk program.
This struct holds state information about the current hfp connection.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
enum ast_frame_type frametype
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.
static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf)
Send an SMS message from the queue.
struct ast_format * format
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
This struct holds HFP features the AG supports.
unsigned int needcallerid
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf)
Parse a CLIP event.
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application'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
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.
Structure for mutex and tracking information.
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.
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
static int hfp_parse_cind(struct hfp_pvt *hfp, char *buf)
Read the result of the AT+CIND? command.
#define AST_APP_ARG(name)
Define an application argument.
static int mbl_has_service(struct mbl_pvt *pvt)
Check if a mobile device has service.
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...