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 133 char rfcomm_buf[256];
145 short alignment_samples[4];
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";
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";
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 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);
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);
481 .description =
"Bluetooth Mobile Device Channel Driver",
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";
517 ast_cli(a->
fd,
FORMAT1,
"ID",
"Address",
"Group",
"Adapter",
"Connected",
"State",
"SMS");
521 ba2str(&pvt->
addr, bdaddr);
522 snprintf(group,
sizeof(group),
"%d", pvt->
group);
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";
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);
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");
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";
633 if (!strcmp(pvt->
id, a->
argv[2]))
649 snprintf(buf,
sizeof(buf),
"%s\r", a->
argv[3]);
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";
681 if (!strcmp(pvt->
id, a->
argv[2]))
697 snprintf(buf,
sizeof(buf),
"%s", a->
argv[3]);
699 ast_cli(a->
fd,
"[%s] error sending CUSD\n", pvt->
id);
742 if (!strcmp(pvt->
id,
args.device))
756 snprintf(status,
sizeof(status),
"%d", stat);
788 ast_log(
LOG_ERROR,
"NULL destination for message -- SMS will not be sent.\n");
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);
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);
866 cidinfo ? cidinfo->
cnam : NULL,
867 0, 0, pvt->
context, assignedids, requestor, 0,
884 ast_channel_language_set(chn,
"en");
904 char *dest_dev =
NULL;
905 char *dest_num =
NULL;
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]);
940 }
else if (!strcmp(pvt->
id, dest_dev)) {
946 ast_log(
LOG_WARNING,
"Request to call on device %s which is not connected / already in use.\n", dest_dev);
974 char *dest_num =
NULL;
981 dest_num = strchr(dest_dev,
'/');
1039 ast_debug(1,
"[%s] hanging up device\n", pvt->
id);
1098 ast_debug(1,
"[%s] error sending digit %c\n", pvt->
id, digit);
1129 pvt->
fr.
src =
"Mobile";
1139 ast_debug(1,
"[%s] read error %d, going to wait for new connection\n", pvt->
id,
errno);
1155 }
while (fr ==
NULL);
1201 ast_debug(1,
"fixup failed, no pvt on newchan\n");
1206 if (pvt->
owner == oldchan)
1207 pvt->
owner = newchan;
1223 ast_debug(1,
"Checking device state for device %s\n", device);
1227 if (!strcmp(pvt->
id, device))
1289 for (i=buflen, p=buf+buflen-1; i>0; i--, p--)
1297 for (i=0, a=0; i<buflen/2; i++) {
1311 ast_debug(1,
"Alignment Detection Triggered.\n");
1393 struct sockaddr_rc addr;
1396 if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
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) {
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) {
1459 ast_debug(1,
"rfcomm_write() (%d) [%.*s]\n", rsock, (
int) count, buf);
1461 if ((out_count = write(rsock, p, count)) == -1) {
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) {
1533 if (*result != expected) {
1569 while ((res = read(rsock, &c, 1)) == 1) {
1574 }
else if (res == -2) {
1736 }
else if (res != -2) {
1748 if (*in_count >= 5 && !strncmp(*buf - *in_count,
"+CMGR", 5)) {
1768 while ((res = read(rsock, &c, 1)) == 1) {
1811 size_t in_count = 0;
1816 }
else if (res == -2) {
1836 struct sockaddr_sco addr;
1839 if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 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) {
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) {
1877 ast_debug(3,
"sco_write() not ready\n");
1883 r = write(s, buf, len);
1901 struct sockaddr_sco addr;
1906 struct sco_options so;
1909 addrlen =
sizeof(
struct sockaddr_sco);
1910 if ((sock = accept(fd, (
struct sockaddr *)&addr, &addrlen)) == -1) {
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);
1925 if (!bacmp(&pvt->
addr, &addr.sco_bdaddr))
1945 ast_debug(1,
"incoming audio connection for pvt without owner\n");
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) {
1973 goto e_close_socket;
1975 if (setsockopt(adapter->
sco_socket, SOL_SOCKET, SO_REUSEADDR, &opt,
sizeof(opt)) == -1) {
1977 goto e_close_socket;
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)) {
2081 return "PARSE ERROR";
2083 return "READ ERROR";
2107 return "SMS PROMPT";
2109 return "+CMS ERROR";
2113 return "NO DIALTONE";
2115 return "NO CARRIER";
2170 if (!sscanf(buf,
"*ECAV: %2d,%2d,%2d", &ccid, &ccstatus, &calltype)) {
2201 if (!sscanf(buf,
"+CIEV: %d,%d", &i, value)) {
2207 ast_debug(2,
"[%s] CIEV event index too high (%s)\n", hfp->
owner->
id, buf);
2224 static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp,
char *
buf)
2236 ast_debug(3,
"[%s] hfp_parse_clip is processing \"%s\"\n", hfp->owner->id,
buf);
2238 for (i = 1; i <
ARRAY_LEN(tokens); i++) {
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]]);
2249 ast_debug(1,
"[%s] hfp_parse_clip invalid cidinfo.cnum data \"%s\" - deleting\n",
2250 hfp->owner->id, cidinfo.
cnum);
2258 cidinfo.
cnam = &
buf[tokens[5]];
2259 if (
buf[tokens[5]] ==
'\0' &&
buf[tokens[4]] ==
'\0') {
2262 while (
buf[i] ==
' ') {
2265 if (
buf[i] ==
'"') {
2273 for (cnamtmp = cidinfo.
cnam; *cnamtmp !=
'\0'; cnamtmp++) {
2274 if (!strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789-,abcdefghijklmnopqrstuvwxyz_", *cnamtmp)) {
2280 ast_debug(2,
"[%s] hfp_parse_clip replaced %d invalid byte(s) in cnam data\n",
2281 hfp->owner->id, invalid);
2283 ast_debug(2,
"[%s] hfp_parse_clip returns cnum=%s and cnam=%s\n",
2284 hfp->owner->id, cidinfo.
cnum, cidinfo.
cnam);
2302 for (index = start;
string[index] != 0; index++) {
2303 if ((
string[index] == delim) && !quoting ) {
2305 string[index] =
'\0';
2308 }
else if (
string[index] ==
'"' && !quoting) {
2311 }
else if (
string[index] ==
'"' ) {
2333 if (!sscanf(buf,
"+CMTI: %*[^,],%d", &index)) {
2363 for (i = 0; i < s && state != 6; i++) {
2366 if (buf[i] ==
',') {
2371 if (buf[i] ==
'"') {
2377 *from_number = &buf[i];
2382 if (buf[i] ==
'"') {
2388 if (buf[i] ==
'\n') {
2418 int i, message_start, message_end;
2430 for (i = 0; i < s; i++) {
2431 if (buf[i] ==
'"') {
2432 message_start = i + 1;
2437 if (message_start == 0 || message_start >= s) {
2442 for (i = s; i > 0; i--) {
2443 if (buf[i] ==
'"') {
2449 if (message_end == 0) {
2453 if (message_start >= message_end) {
2457 cusd = &buf[message_start];
2458 buf[message_end] =
'\0';
2517 snprintf(cmd,
sizeof(cmd),
"AT+BRSF=%d\r",
hfp_brsf2int(brsf));
2547 snprintf(cmd,
sizeof(cmd),
"AT+CMER=3,0,0,%d\r", status ? 1 : 0);
2559 snprintf(cmd,
sizeof(cmd),
"AT+VGS=%d\r", value);
2569 static int hfp_send_vgm(
struct hfp_pvt *hfp,
int value)
2572 snprintf(cmd,
sizeof(cmd),
"AT+VGM=%d\r", value);
2586 snprintf(cmd,
sizeof(cmd),
"AT+CLIP=%d\r", status ? 1 : 0);
2613 snprintf(cmd,
sizeof(cmd),
"AT+VTS=%c\r", digit);
2628 snprintf(cmd,
sizeof(cmd),
"AT+CMGF=%d\r", mode);
2649 snprintf(cmd,
sizeof(cmd),
"AT+CMGR=%d\r", index);
2661 snprintf(cmd,
sizeof(cmd),
"AT+CMGS=\"%s\"\r", number);
2673 snprintf(cmd,
sizeof(cmd),
"%.160s\x1a", message);
2694 snprintf(cmd,
sizeof(cmd),
"ATD%s;\r", number);
2715 snprintf(cmd,
sizeof(cmd),
"AT+CUSD=1,\"%s\",15\r", code);
2728 if (!sscanf(buf,
"+BRSF:%d", &brsf))
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));
2752 if (!sscanf(indicator,
"%d", &value)) {
2753 ast_debug(1,
"error parsing CIND state '%s' for group %d\n", indicator, group);
2781 for (i = 0; i < s; i++) {
2784 if (buf[i] ==
' ') {
2790 indicator = &buf[i];
2794 if (buf[i] ==
',') {
2832 for (i = 0; i < s; i++) {
2835 if (buf[i] ==
'(') {
2841 if (buf[i] ==
'"') {
2846 indicator = &buf[i];
2850 if (buf[i] ==
'"') {
2856 if (buf[i] ==
'(') {
2864 if (buf[i] ==
')') {
2871 if (!strcmp(indicator,
"service")) {
2874 }
else if (!strcmp(indicator,
"call")) {
2877 }
else if (!strcmp(indicator,
"callsetup")) {
2881 }
else if (!strcmp(indicator,
"call_setup")) {
2885 }
else if (!strcmp(indicator,
"callheld")) {
2888 }
else if (!strcmp(indicator,
"signal")) {
2891 }
else if (!strcmp(indicator,
"roam")) {
2894 }
else if (!strcmp(indicator,
"battchg")) {
2899 ast_debug(2,
"ignoring unknown CIND indicator '%s'\n", indicator);
2902 ast_debug(1,
"can't store indicator %d (%s), we only support up to %d indicators", group, indicator, (
int)
sizeof(hfp->
cind_index));
2946 snprintf(cmd,
sizeof(cmd),
"\r\n+VGS=%d\r\n", gain);
2958 snprintf(cmd,
sizeof(cmd),
"\r\n+VGM=%d\r\n", gain);
3077 uint32_t range = 0x0000ffff;
3078 sdp_list_t *response_list, *search_list, *attrid_list;
3080 sdp_list_t *proto_list;
3081 sdp_record_t *sdprec;
3083 str2ba(addr, &bdaddr);
3085 session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
3087 ast_debug(1,
"sdp_connect() failed on device %s.\n", addr);
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);
3097 if (response_list) {
3098 sdprec = (sdp_record_t *) response_list->data;
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);
3104 sdp_record_free(sdprec);
3105 sdp_list_free(response_list, 0);
3107 ast_debug(1,
"No responses returned for device %s.\n", addr);
3109 ast_debug(1,
"sdp_service_search_attr_req() failed on device %s.\n", addr);
3111 sdp_list_free(search_list, 0);
3112 sdp_list_free(attrid_list, 0);
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";
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;
3133 sdp_record_t *record = sdp_record_alloc();
3135 sdp_uuid128_create(&svc_uuid, &service_uuid_int);
3136 sdp_set_service_id(record, svc_uuid);
3138 sdp_uuid32_create(&svc_class1_uuid, GENERIC_AUDIO_SVCLASS_ID);
3139 sdp_uuid32_create(&svc_class2_uuid, HEADSET_PROFILE_ID);
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);
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 );
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);
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);
3159 access_proto_list = sdp_list_append(0, proto_list);
3160 sdp_set_access_protos(record, access_proto_list);
3162 sdp_set_info_attr(record, service_name, service_prov, service_dsc);
3164 if (!(session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY)))
3167 if (sdp_record_register(session, record, 0) < 0) {
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);
3201 ast_debug(1,
"[%s] error parsing BRSF\n", pvt->
id);
3206 ast_debug(1,
"[%s] error handling BRSF\n", pvt->
id);
3214 ast_debug(1,
"[%s] received unexpected AT message 'BRSF'\n", pvt->
id);
3238 ast_debug(1,
"[%s] error performing CIND test\n", pvt->
id);
3244 ast_debug(1,
"[%s] error getting CIND state\n", pvt->
id);
3249 ast_debug(1,
"[%s] error getting CIND state\n", pvt->
id);
3256 ast_debug(1,
"[%s] received unexpected AT message 'CIND'\n", pvt->
id);
3281 ast_debug(1,
"[%s] BSRF sent successfully\n", pvt->
id);
3287 ast_debug(1,
"[%s] error sending CMER\n", pvt->
id);
3292 ast_debug(1,
"[%s] error sending CIND test\n", pvt->
id);
3298 ast_debug(1,
"[%s] CIND test sent successfully\n", pvt->
id);
3305 ast_debug(1,
"[%s] error requesting CIND state\n", pvt->
id);
3310 ast_debug(1,
"[%s] CIND sent successfully\n", pvt->
id);
3314 ast_verb(3,
"Bluetooth Device %s has a call in progress - delaying connection.\n", pvt->
id);
3322 ast_debug(1,
"[%s] error sending CMER\n", pvt->
id);
3327 ast_debug(1,
"[%s] error enabling calling line notification\n", pvt->
id);
3333 ast_debug(1,
"[%s] CMER sent successfully\n", pvt->
id);
3339 ast_debug(1,
"[%s] error sending CIND test\n", pvt->
id);
3344 ast_debug(1,
"[%s] error enabling calling line notification\n", pvt->
id);
3350 ast_debug(1,
"[%s] caling line indication enabled\n", pvt->
id);
3352 ast_debug(1,
"[%s] error enabling Sony Ericsson call monitoring extensions\n", pvt->
id);
3358 ast_debug(1,
"[%s] Sony Ericsson call monitoring is active on device\n", pvt->
id);
3360 ast_debug(1,
"[%s] error synchronizing gain settings\n", pvt->
id);
3366 ast_verb(3,
"Bluetooth Device %s initialized and ready.\n", pvt->
id);
3370 ast_debug(1,
"[%s] volume level synchronization successful\n", pvt->
id);
3375 ast_debug(1,
"[%s] error setting CMGF\n", pvt->
id);
3381 ast_debug(1,
"[%s] sms text mode enabled\n", pvt->
id);
3384 ast_debug(1,
"[%s] error setting CNMI\n", pvt->
id);
3389 ast_debug(1,
"[%s] sms new message indication enabled\n", pvt->
id);
3395 ast_debug(1,
"[%s] answer sent successfully\n", pvt->
id);
3399 ast_debug(1,
"[%s] dial sent successfully\n", pvt->
id);
3405 ast_debug(1,
"[%s] successful hangup\n", pvt->
id);
3408 ast_debug(1,
"[%s] successfully sent sms message\n", pvt->
id);
3412 ast_debug(1,
"[%s] digit sent successfully\n", pvt->
id);
3415 ast_debug(1,
"[%s] CUSD code sent successfully\n", pvt->
id);
3426 ast_debug(1,
"[%s] received unexpected AT message 'OK'\n", pvt->
id);
3455 ast_debug(1,
"[%s] error reading BSRF\n", pvt->
id);
3458 ast_debug(1,
"[%s] error during CIND test\n", pvt->
id);
3461 ast_debug(1,
"[%s] error requesting CIND state\n", pvt->
id);
3464 ast_debug(1,
"[%s] error during CMER request\n", pvt->
id);
3467 ast_debug(1,
"[%s] error enabling calling line indication\n", pvt->
id);
3470 ast_debug(1,
"[%s] volume level synchronization failed\n", pvt->
id);
3476 ast_debug(1,
"[%s] error setting CMGF\n", pvt->
id);
3482 ast_debug(1,
"[%s] error setting CMGF\n", pvt->
id);
3487 ast_debug(1,
"[%s] error setting CNMI\n", pvt->
id);
3491 ast_debug(1,
"[%s] Mobile does not support Sony Ericsson extensions\n", pvt->
id);
3496 ast_debug(1,
"[%s] error synchronizing gain settings\n", pvt->
id);
3502 ast_verb(3,
"Bluetooth Device %s initialized and ready.\n", pvt->
id);
3517 ast_debug(1,
"[%s] error sending hangup, disconnecting\n", pvt->
id);
3520 ast_debug(1,
"[%s] error reading sms message\n", pvt->
id);
3524 ast_debug(1,
"[%s] error sending sms message\n", pvt->
id);
3528 ast_debug(1,
"[%s] error sending digit\n", pvt->
id);
3531 ast_verb(0,
"[%s] error sending CUSD command\n", pvt->
id);
3542 ast_debug(1,
"[%s] received unexpected AT message 'ERROR'\n", pvt->
id);
3566 ast_debug(1,
"[%s] line disconnected\n", pvt->
id);
3581 ast_debug(1,
"[%s] remote end answered\n", pvt->
id);
3587 ast_verb(3,
"[%s] user answered bluetooth device from handset, disconnecting\n", pvt->
id);
3615 ast_debug(1,
"[%s] incoming call, waiting for caller id\n", pvt->
id);
3624 ast_verb(3,
"[%s] user dialed from handset, disconnecting\n", pvt->
id);
3638 ast_debug(1,
"[%s] error parsing CIND: %s\n", pvt->
id, buf);
3694 ast_debug(1,
"[%s] got ring while waiting for caller id\n", pvt->
id);
3712 ast_debug(1,
"[%s] incoming sms message\n", pvt->
id);
3716 ast_debug(1,
"[%s] error sending CMGR to retrieve SMS message\n", pvt->
id);
3723 ast_debug(1,
"[%s] error parsing incoming sms message alert, disconnecting\n", pvt->
id);
3745 ast_debug(1,
"[%s] error parsing sms message, disconnecting\n", pvt->
id);
3749 ast_debug(1,
"[%s] successfully read sms message\n", pvt->
id);
3754 ast_debug(1,
"[%s] error creating sms message channel, disconnecting\n", pvt->
id);
3767 ast_debug(1,
"[%s] got unexpected +CMGR message, ignoring\n", pvt->
id);
3784 ast_debug(1,
"[%s] error, got sms prompt with no pending sms messages\n", pvt->
id);
3789 ast_debug(1,
"[%s] error, got sms prompt but no pending sms messages\n", pvt->
id);
3796 ast_debug(1,
"[%s] error sending sms message\n", pvt->
id);
3816 ast_verb(0,
"[%s] error parsing CUSD: %s\n", pvt->
id, buf);
3820 ast_verb(0,
"[%s] CUSD response: %s\n", pvt->
id, cusd);
3848 ast_verb(1,
"[%s] mobile reports NO DIALTONE\n", pvt->
id);
3863 ast_verb(1,
"[%s] mobile reports NO CARRIER\n", pvt->
id);
3873 struct hfp_pvt *hfp = pvt->
hfp;
3900 ast_debug(1,
"[%s] timeout waiting for rfcomm data, disconnecting\n", pvt->
id);
3909 ast_debug(1,
"[%s] timeout during CIND test, try setting 'blackberry=yes'\n", hfp->
owner->
id);
3913 ast_debug(1,
"[%s] timeout after sending CMER, try setting 'blackberry=no'\n", hfp->
owner->
id);
4059 ast_debug(1,
"[%s] ignoring unknown message: %s\n", pvt->
id, buf);
4062 ast_debug(1,
"[%s] error parsing message\n", pvt->
id);
4075 ast_verb(3,
"Error initializing Bluetooth device %s.\n", pvt->
id);
4079 ast_debug(1,
"[%s] device disconnected, hanging up owner\n", pvt->
id);
4096 ast_verb(3,
"Bluetooth Device %s has disconnected.\n", pvt->
id);
4113 ast_debug(1,
"[%s] error sending RING\n", pvt->
id);
4128 ast_verb(3,
"Bluetooth Device %s initialised and ready.\n", pvt->
id);
4154 ast_debug(1,
"[%s] error sending AT message 'OK'\n", pvt->
id);
4183 ast_debug(1,
"[%s] error sending VGS/VGM\n", pvt->
id);
4226 ast_debug(1,
"[%s] error sending AT message 'ERROR'\n", pvt->
id);
4236 ast_debug(1,
"[%s] device disconnected, hanging up owner\n", pvt->
id);
4255 ast_verb(3,
"Bluetooth Device %s has disconnected\n", pvt->
id);
4291 if (!adapter->
inuse) {
4301 ast_verb(3,
"Bluetooth Device %s has connected, initializing...\n", pvt->
id);
4369 struct hci_dev_req dr;
4380 ast_debug(1,
"Reading configuration for adapter %s %s.\n",
id, address);
4382 if (!(adapter =
ast_calloc(1,
sizeof(*adapter)))) {
4388 str2ba(address, &adapter->
addr);
4391 adapter->
dev_id = hci_devid(address);
4394 ast_log(
LOG_ERROR,
"Skipping adapter %s. Unable to communicate with adapter.\n", adapter->
id);
4395 goto e_free_adapter;
4399 hci_read_voice_setting(adapter->
hci_socket, &vs, 1000);
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;
4407 if (!strcasecmp(v->
name,
"forcemaster")) {
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);
4416 }
else if (!strcasecmp(v->
name,
"alignmentdetection")) {
4423 ast_log(
LOG_ERROR,
"Unable to create I/O context for audio connection listener\n");
4424 goto e_hci_close_dev;
4428 ast_log(
LOG_ERROR,
"Unable to create I/O context for audio connections\n");
4429 goto e_destroy_accept_io;
4434 ast_log(
LOG_ERROR,
"Skipping adapter %s. Error binding audio connection listerner socket.\n", adapter->
id);
4440 ast_log(
LOG_ERROR,
"Skipping adapter %s. Error adding listener socket to I/O context.\n", adapter->
id);
4446 ast_log(
LOG_ERROR,
"Skipping adapter %s. Error creating audio connection listerner thread.\n", adapter->
id);
4454 ast_debug(1,
"Loaded adapter %s %s.\n", adapter->
id, address);
4464 e_destroy_accept_io:
4485 const char *
address, *adapter_str, *port;
4486 ast_debug(1,
"Reading configuration for device %s.\n", cat);
4497 if (!strcmp(adapter->
id, adapter_str))
4502 ast_log(
LOG_ERROR,
"Skiping device %s. Unknown adapter '%s' specified.\n", cat, adapter_str);
4509 ast_log(
LOG_ERROR,
"Skipping device %s. Missing required port or address setting.\n", cat);
4530 str2ba(address, &pvt->
addr);
4541 ast_log(
LOG_ERROR,
"Skipping device %s. Error setting up frame bt_out_smoother.\n", cat);
4547 ast_log(
LOG_ERROR,
"Skipping device %s. Error setting up frame bt_in_smoother.\n", cat);
4548 goto e_free_bt_out_smoother;
4553 ast_log(
LOG_ERROR,
"Skipping device %s. Error setting up dsp for dtmf detection.\n", cat);
4554 goto e_free_bt_in_smoother;
4559 ast_log(
LOG_ERROR,
"Unable to create scheduler context for headset device\n");
4567 if (!strcasecmp(v->
name,
"type")) {
4568 if (!strcasecmp(v->
value,
"headset"))
4572 }
else if (!strcasecmp(v->
name,
"context")) {
4574 }
else if (!strcasecmp(v->
name,
"group")) {
4577 }
else if (!strcasecmp(v->
name,
"sms")) {
4579 }
else if (!strcasecmp(v->
name,
"nocallsetup")) {
4583 ast_debug(1,
"Setting nocallsetup mode for device %s.\n", pvt->
id);
4584 }
else if (!strcasecmp(v->
name,
"blackberry")) {
4614 e_free_bt_in_smoother:
4616 e_free_bt_out_smoother:
4640 if (!strcasecmp(v->
name,
"interval")) {
4642 ast_log(
LOG_NOTICE,
"error parsing 'interval' in general section, using default value\n");
4649 if (!strcasecmp(cat,
"adapter")) {
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" 4667 if (strcasecmp(cat,
"general") && strcasecmp(cat,
"adapter")) {
4787 dev_id = hci_get_route(
NULL);
4789 s = hci_open_dev(dev_id);
4790 if (dev_id < 0 || s < 0) {
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
struct ast_variable * next
static int mbl_queue_hangup(struct mbl_pvt *pvt)
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
static int handle_response_busy(struct mbl_pvt *pvt)
Handle BUSY messages.
char context[AST_MAX_CONTEXT]
enum sip_cc_notify_state state
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.
#define HFP_CIND_CALL_ACTIVE
#define AST_CLI_DEFINE(fn, txt,...)
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.
#define AST_CAUSE_INCOMPATIBLE_DESTINATION
#define CHANNEL_FRAME_SIZE
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.
static int sco_connect(bdaddr_t src, bdaddr_t dst)
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel)
#define ast_smoother_feed(s, f)
struct ast_smoother * ast_smoother_new(int bytes)
static int rfcomm_wait(int rsock, int *ms)
Wait for activity on an rfcomm socket.
static struct ast_cli_entry mbl_cli[]
#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 load_module(void)
struct ast_smoother * bt_in_smoother
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...
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
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.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
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.
void ast_dsp_free(struct ast_dsp *dsp)
#define DSP_FEATURE_DIGIT_DETECT
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
static struct hfp_hf hfp_our_brsf
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)
Convenient Signal Processing routines.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#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.
#define DEADLOCK_AVOIDANCE(lock)
descriptor for a cli entry.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
#define HFP_CIND_CALLSETUP
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.
static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen)
static int unloading_flag
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static char * handle_cli_mobile_cusd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 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.
static int mbl_hangup(struct ast_channel *ast)
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.
unsigned int do_alignment_detection
static const struct adsi_event events[]
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define HFP_CIND_CALL_NONE
static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)