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 80 
  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";
 
  249static int sdp_search(
char *addr, 
int profile);
 
  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 
  374static int parse_next_token(
char string[], 
const int start, 
const char delim);
 
  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);
 
 
  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]");
 
  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]))
 
  639        ast_cli(
a->fd, 
"Device %s not found.\n", 
a->argv[2]);
 
  645        ast_cli(
a->fd, 
"Device %s not connected.\n", 
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]))
 
  687        ast_cli(
a->fd, 
"Device %s not found.\n", 
a->argv[2]);
 
  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);
 
 
  742        if (!strcmp(pvt->
id, 
args.device))
 
 
  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);
 
 
  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);
 
 
 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) 
 1491static 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");
 
 
 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;
 
 
 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";
 
 
 2172    if (!sscanf(
buf, 
"*ECAV: %2d,%2d,%2d", &ccid, &ccstatus, &calltype)) {
 
 
 2203    if (!sscanf(
buf, 
"+CIEV: %d,%d", &i, 
value)) {
 
 
 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",
 
 2261    if (
buf[tokens[5]] == 
'\0' && 
buf[tokens[4]] == 
'\0') {
 
 2264        while (
buf[i] == 
' ') {     
 
 2267        if (
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",
 
 
 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)) {
 
 
 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';
 
 
 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);
 
 
 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))
 
 
 2783    for (i = 0; i < s; i++) {
 
 2786            if (
buf[i] == 
' ') {
 
 2796            if (
buf[i] == 
',') {
 
 
 2834    for (i = 0; i < s; i++) {
 
 2837            if (
buf[i] == 
'(') {
 
 2843            if (
buf[i] == 
'"') {
 
 2852            if (
buf[i] == 
'"') {
 
 2858            if (
buf[i] == 
'(') {
 
 2866            if (
buf[i] == 
')') {
 
 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")) {
 
 
 2948    snprintf(cmd, 
sizeof(cmd), 
"\r\n+VGS=%d\r\n", gain);
 
 
 2960    snprintf(cmd, 
sizeof(cmd), 
"\r\n+VGM=%d\r\n", gain);
 
 
 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);
 
 
 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;
 
 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)))
 
 3169        if (sdp_record_register(
session, record, 0) < 0) {
 
 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);
 
 
 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);
 
 
 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);
 
 
 3279        switch (
entry->response_to) {
 
 3283            ast_debug(1, 
"[%s] BSRF sent successfully\n", pvt->
id);
 
 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);
 
 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);
 
 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);
 
 3428        ast_debug(1, 
"[%s] received unexpected AT message 'OK'\n", pvt->
id);
 
 
 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);
 
 3489            ast_debug(1, 
"[%s] error setting CNMI\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);
 
 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);
 
 3544        ast_debug(1, 
"[%s] received unexpected AT message 'ERROR'\n", pvt->
id);
 
 
 3568            ast_debug(1, 
"[%s] line disconnected\n", pvt->
id);
 
 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);
 
 3617            ast_debug(1, 
"[%s] incoming call, waiting for caller id\n", pvt->
id);
 
 3626                ast_verb(3, 
"[%s] user dialed from handset, disconnecting\n", pvt->
id);
 
 
 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);
 
 
 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);
 
 3769        ast_debug(1, 
"[%s] got unexpected +CMGR message, ignoring\n", pvt->
id);
 
 
 3786        ast_debug(1, 
"[%s] error, got sms prompt with no pending sms messages\n", pvt->
id);
 
 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);
 
 
 3822    ast_verb(0, 
"[%s] CUSD response: %s\n", pvt->
id, cusd);
 
 
 3850    ast_verb(1, 
"[%s] mobile reports NO DIALTONE\n", pvt->
id);
 
 
 3865    ast_verb(1, 
"[%s] mobile reports NO CARRIER\n", pvt->
id);
 
 
 3902            ast_debug(1, 
"[%s] timeout waiting for rfcomm data, disconnecting\n", pvt->
id);
 
 3906                    switch (
entry->response_to) {
 
 3911                            ast_debug(1, 
"[%s] timeout during CIND test, try setting 'blackberry=yes'\n", hfp->
owner->
id);
 
 3915                            ast_debug(1, 
"[%s] timeout after sending CMER, try setting 'blackberry=no'\n", hfp->
owner->
id);
 
 4061            ast_debug(1, 
"[%s] ignoring unknown message: %s\n", pvt->
id, 
buf);
 
 4064            ast_debug(1, 
"[%s] error parsing message\n", pvt->
id);
 
 4077        ast_verb(3, 
"Error initializing Bluetooth device %s.\n", pvt->
id);
 
 4081        ast_debug(1, 
"[%s] device disconnected, hanging up owner\n", pvt->
id);
 
 4098    ast_verb(3, 
"Bluetooth Device %s has disconnected.\n", pvt->
id);
 
 
 4115        ast_debug(1, 
"[%s] error sending RING\n", pvt->
id);
 
 
 4130    ast_verb(3, 
"Bluetooth Device %s initialised and ready.\n", pvt->
id);
 
 4156                ast_debug(1, 
"[%s] error sending AT message 'OK'\n", pvt->
id);
 
 4185                        ast_debug(1, 
"[%s] error sending VGS/VGM\n", pvt->
id);
 
 4228                ast_debug(1, 
"[%s] error sending AT message 'ERROR'\n", pvt->
id);
 
 4238        ast_debug(1, 
"[%s] device disconnected, hanging up owner\n", pvt->
id);
 
 4257    ast_verb(3, 
"Bluetooth Device %s has disconnected\n", pvt->
id);
 
 
 4303                                ast_verb(3, 
"Bluetooth Device %s has connected, initializing...\n", pvt->
id);
 
 
 4371    struct hci_dev_req 
dr;
 
 4384    if (!(adapter = 
ast_calloc(1, 
sizeof(*adapter)))) {
 
 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;
 
 4409        if (!strcasecmp(v->
name, 
"forcemaster")) {
 
 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);
 
 
 4487    const char *
address, *adapter_str, *port;
 
 4488    ast_debug(1, 
"Reading configuration for device %s.\n", cat);
 
 4499        if (!strcmp(adapter->
id, adapter_str))
 
 4504        ast_log(
LOG_ERROR, 
"Skipping device %s. Unknown adapter '%s' specified.\n", cat, adapter_str);
 
 4511        ast_log(
LOG_ERROR, 
"Skipping device %s. Missing required port or address setting.\n", cat);
 
 4543        ast_log(
LOG_ERROR, 
"Skipping device %s. Error setting up frame bt_out_smoother.\n", cat);
 
 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");
 
 4569        if (!strcasecmp(v->
name, 
"type")) {
 
 4570            if (!strcasecmp(v->
value, 
"headset"))
 
 4574        } 
else if (!strcasecmp(v->
name, 
"context")) {
 
 4576        } 
else if (!strcasecmp(v->
name, 
"group")) {
 
 4579        } 
else if (!strcasecmp(v->
name, 
"sms")) {
 
 4581        } 
else if (!strcasecmp(v->
name, 
"nocallsetup")) {
 
 4585                ast_debug(1, 
"Setting nocallsetup mode for device %s.\n", pvt->
id);
 
 4586        } 
else if (!strcasecmp(v->
name, 
"blackberry")) {
 
 4616e_free_bt_in_smoother:
 
 4618e_free_bt_out_smoother:
 
 
 4642        if (!strcasecmp(v->
name, 
"interval")) {
 
 4644                ast_log(
LOG_NOTICE, 
"error parsing 'interval' in general section, using default value\n");
 
 4651        if (!strcasecmp(cat, 
"adapter")) {
 
 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")) {
 
 
 4791    s = hci_open_dev(
dev_id);
 
 4792    if (
dev_id < 0 || s < 0) {
 
 
void ast_cli_unregister_multiple(void)
static const struct adsi_event events[]
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_isphonenumber(const char *n)
Check if a string consists only of digits and + #.
Internal Asterisk hangup causes.
#define AST_CAUSE_INCOMPATIBLE_DESTINATION
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
#define AST_CAUSE_FACILITY_NOT_IMPLEMENTED
#define AST_CAUSE_USER_BUSY
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...
static int mbl_hangup(struct ast_channel *ast)
static char * mblsendsms_desc
static struct adapter_pvt * mbl_load_adapter(struct ast_config *cfg, const char *cat)
Load an adapter from the configuration file.
static int handle_response_brsf(struct mbl_pvt *pvt, char *buf)
Handle the BRSF response.
static int hsp_send_ring(int rsock)
Send a RING unsolicited AT response.
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.
static void * do_monitor_headset(void *data)
static int discovery_interval
static int hfp_send_brsf(struct hfp_pvt *hfp, struct hfp_hf *brsf)
Send a BRSF request.
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
static int handle_response_cmti(struct mbl_pvt *pvt, char *buf)
Handle AT+CMTI messages.
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 void * do_monitor_phone(void *data)
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
static int mbl_call(struct ast_channel *ast, const char *dest, int timeout)
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.
static int handle_response_clip(struct mbl_pvt *pvt, char *buf)
Handle AT+CLIP messages.
static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text)
Parse a CMGR message.
static int sco_bind(struct adapter_pvt *adapter)
Bind an SCO listener socket for the given adapter.
static int hsp_send_error(int rsock)
Send an ERROR AT response.
static void * do_sco_listen(void *data)
Service new and existing SCO connections. This thread accepts new sco connections and handles audio d...
static ssize_t rfcomm_read(int rsock, char *buf, size_t count)
Read one Hayes AT message from an rfcomm socket.
static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
Handle AT+CIEV messages.
static char * handle_cli_mobile_cusd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define DEVICE_FRAME_FORMAT
static int hfp_send_cind(struct hfp_pvt *hfp)
Send the CIND read command.
static struct hfp_ag * hfp_int2brsf(int brsf, struct hfp_ag *ag)
Convert a BRSF int to an hfp_ag struct.
static int rfcomm_read_cmgr(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of a +CMGR message.
static int handle_response_cind(struct mbl_pvt *pvt, char *buf)
Handle the CIND response.
static int hfp_send_sms_text(struct hfp_pvt *hfp, const char *message)
Send the text of an SMS message.
#define HFP_CIND_CALL_ACTIVE
static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf)
Parse a CMTI notification.
static char * app_mblsendsms
static int hfp_parse_cind_indicator(struct hfp_pvt *hfp, int group, char *indicator)
Parse and store the given indicator.
static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf)
Handle AT+CMGR messages.
static void msg_queue_flush(struct mbl_pvt *pvt)
Remove all items from the queue and free them.
#define rfcomm_read_debug(c)
static int hfp_send_cnmi(struct hfp_pvt *hfp)
Setup SMS new message indication.
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.
static int hfp_send_atd(struct hfp_pvt *hfp, const char *number)
Send ATD.
#define HFP_CIND_CALLSETUP
static int handle_response_ring(struct mbl_pvt *pvt, char *buf)
Handle RING messages.
static int mbl_status_exec(struct ast_channel *ast, const char *data)
static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode)
Set the SMS mode.
static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)
#define DEVICE_FRAME_SIZE
static void * do_discovery(void *data)
#define CHANNEL_FRAME_SIZE
static int at_match_prefix(char *buf, char *prefix)
Match the given buffer with the given prefix.
static int sdp_search(char *addr, int profile)
static sdp_session_t * sdp_session
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 char * handle_cli_mobile_rfcomm(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define HFP_CIND_CALL_NONE
static char * mblstatus_desc
static int mbl_load_config(void)
static int hfp_send_dtmf(struct hfp_pvt *hfp, char digit)
Send a DTMF command.
static struct mbl_pvt * mbl_load_device(struct ast_config *cfg, const char *cat)
Load a device from the configuration file.
static int rfcomm_wait(int rsock, int *ms)
Wait for activity on an rfcomm socket.
#define HFP_CIND_SERVICE_AVAILABLE
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.
static int rfcomm_read_result(int rsock, char **buf, size_t count, size_t *in_count)
Read and AT result code.
static struct hfp_hf hfp_our_brsf
static int handle_response_busy(struct mbl_pvt *pvt)
Handle BUSY messages.
static void set_unloading(void)
Set the unloading flag.
static int hfp_send_vgs(struct hfp_pvt *hfp, int value)
Send the current speaker gain level.
static int mbl_queue_hangup(struct mbl_pvt *pvt)
static int mbl_sendsms_exec(struct ast_channel *ast, const char *data)
static int check_unloading(void)
Check if the module is unloading.
static int hsp_send_vgm(int rsock, int gain)
Send a microphone gain unsolicited AT response.
static struct ast_cli_entry mbl_cli[]
static char * app_mblstatus
static int handle_response_ok(struct mbl_pvt *pvt, char *buf)
Handle OK AT messages.
static int headset_send_ring(const void *data)
static int hsp_send_ok(int rsock)
Send an OK AT response.
static int rfcomm_read_command(int rsock, char **buf, size_t count, size_t *in_count)
Read the remainder of an AT command.
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)
static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value)
Parse a CIEV event.
static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
static int hfp_send_ata(struct hfp_pvt *hfp)
Send ATA.
static int mbl_has_service(struct mbl_pvt *pvt)
Check if a mobile device has service.
static char * mblstatus_synopsis
static int rfcomm_write_full(int rsock, char *buf, size_t count)
Write to an rfcomm socket.
#define HFP_CIND_CALLSETUP_INCOMING
static char * handle_cli_mobile_search(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hfp_parse_cind_test(struct hfp_pvt *hfp, char *buf)
Parse the result of the AT+CIND=? command.
static int hfp_send_cmgs(struct hfp_pvt *hfp, const char *number)
Start sending an SMS message.
static int handle_response_cusd(struct mbl_pvt *pvt, char *buf)
Handle CUSD messages.
static int handle_response_error(struct mbl_pvt *pvt, char *buf)
Handle ERROR AT messages.
static int unloading_flag
static int mbl_devicestate(const char *data)
static int rfcomm_read_until_crlf(int rsock, char **buf, size_t count, size_t *in_count)
Read until.
static char * hfp_parse_cusd(struct hfp_pvt *hfp, char *buf)
Parse a CUSD answer.
#define HFP_CIND_CALLSETUP_OUTGOING
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
#define HFP_CIND_CALLHELD
static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf)
Send an SMS message from the queue.
static int load_module(void)
static int mbl_answer(struct ast_channel *ast)
static int hfp_send_ecam(struct hfp_pvt *hfp)
Enable Sony Ericsson extensions / indications.
static int hfp_send_chup(struct hfp_pvt *hfp)
Send AT+CHUP.
static int hfp_send_cind_test(struct hfp_pvt *hfp)
Send the CIND test command.
static struct ast_channel * mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
Parse a ECAV event.
static int hfp_send_cusd(struct hfp_pvt *hfp, const char *code)
Send CUSD.
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
static at_message_t at_read_full(int rsock, char *buf, size_t count)
Read an AT message and classify it.
static int sco_connect(bdaddr_t src, bdaddr_t dst)
static int mbl_ast_hangup(struct mbl_pvt *pvt)
static int unload_module(void)
static pthread_t discovery_thread
static char * handle_cli_mobile_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hfp_send_clip(struct hfp_pvt *hfp, int status)
Enable or disable calling line identification.
static int hfp_parse_cind(struct hfp_pvt *hfp, char *buf)
Read the result of the AT+CIND? command.
static struct ast_frame * mbl_read(struct ast_channel *ast)
static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static int hfp_brsf2int(struct hfp_hf *hf)
Convert a hfp_hf struct to a BRSF int.
static int hsp_send_vgs(int rsock, int gain)
Send a speaker gain unsolicited AT response.
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.
static sdp_session_t * sdp_register(void)
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
#define HFP_CIND_CALLSETUP_NONE
static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf)
Parse BRSF data.
static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen)
static struct ast_channel_tech mbl_tech
#define HFP_CIND_CALLSETUP_ALERTING
static struct msg_queue_entry * msg_queue_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue.
static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel)
static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf)
Parse a CLIP event.
static int rfcomm_read_until_ok(int rsock, char **buf, size_t count, size_t *in_count)
Read until a.
static char * mblsendsms_synopsis
static int start_monitor(struct mbl_pvt *pvt)
static int sco_write(int s, char *buf, int len)
static ast_mutex_t unload_mutex
static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf)
Handle NO CARRIER messages.
static int hfp_send_cmer(struct hfp_pvt *hfp, int status)
Enable or disable indicator events reporting.
static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf)
Handle NO DIALTONE messages.
static int hfp_send_cmgr(struct hfp_pvt *hfp, int index)
Read an SMS message.
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_rings_set(struct ast_channel *chan, int value)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
Waits for input on an fd.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
#define ast_channel_trylock(chan)
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
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 ...
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_channel_unlock(chan)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
ast_channel_state
ast_channel states
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Convenient Signal Processing routines.
void ast_dsp_free(struct ast_dsp *dsp)
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
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,...
#define DSP_FEATURE_DIGIT_DETECT
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
#define DSP_DIGITMODE_DTMF
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
#define DSP_DIGITMODE_RELAXDTMF
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char prefix[MAX_PREFIX]
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
ast_control_frame_type
Internal control frame subtype field values.
struct ast_frame ast_null_frame
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
I/O Management (derived from Cheops-NG)
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...
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
void io_context_destroy(struct io_context *ioc)
Destroys a context.
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
A set of macros to manage forward-linked lists.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE_HEAD
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_HEAD
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Asterisk locking-related definitions:
#define AST_PTHREADT_NULL
#define ast_mutex_init(pmutex)
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
#define DEADLOCK_AVOIDANCE(lock)
#define ast_mutex_unlock(a)
#define ast_mutex_trylock(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
#define EVENT_FLAG_SYSTEM
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
#define ast_register_application(app, execute, synopsis, description)
Register an application.
@ AST_MODPRI_CHANNEL_DRIVER
@ AST_MODULE_SUPPORT_EXTENDED
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Options provided by main asterisk program.
Core PBX routines and definitions.
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.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
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.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
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.
Asterisk internal frame definitions.
void ast_smoother_free(struct ast_smoother *s)
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
#define ast_smoother_feed(s, f)
struct ast_smoother * ast_smoother_new(int bytes)
void ast_smoother_reset(struct ast_smoother *s, int bytes)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_alloca(init_len)
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
pthread_t sco_listener_thread
struct io_context * accept_io
struct adapter_pvt::@0 entry
unsigned int alignment_detection
Structure to pass both assignedid values to channel drivers.
Structure to describe a channel "technology", ie a channel driver See for examples:
struct ast_format_cap * capabilities
Main Channel structure associated with a channel.
descriptor for a cli entry.
Structure used to handle boolean flags.
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
Structure for mutex and tracking information.
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
This struct holds HFP features the AG supports.
This struct holds mappings for indications.
This struct holds HFP features that we support.
This struct holds state information about the current hfp connection.
Global IO variables are now in a struct in order to be made threadsafe.
unsigned int do_alignment_detection
unsigned int outgoing_sms
struct ast_sched_context * sched
short alignment_samples[4]
char io_buf[CHANNEL_FRAME_SIZE+AST_FRIENDLY_OFFSET]
struct mbl_pvt::msg_queue msg_queue
struct ast_smoother * bt_in_smoother
struct ast_smoother * bt_out_smoother
struct ast_channel * owner
struct adapter_pvt * adapter
unsigned int incoming_sms
unsigned int no_callsetup
char context[AST_MAX_CONTEXT]
unsigned int needcallerid
unsigned int alignment_detection_triggered
struct msg_queue_entry::@2 entry
#define ast_pthread_create_background(a, b, c, d)
long int ast_random(void)