Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
chan_mobile.c File Reference

Bluetooth Mobile Device channel driver. More...

#include "asterisk.h"
#include <pthread.h>
#include <signal.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sco.h>
#include <bluetooth/l2cap.h>
#include "asterisk/compat.h"
#include "asterisk/lock.h"
#include "asterisk/callerid.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/cli.h"
#include "asterisk/devicestate.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/io.h"
#include "asterisk/smoother.h"
#include "asterisk/format_cache.h"
Include dependency graph for chan_mobile.c:

Go to the source code of this file.

Data Structures

struct  adapter_pvt
 
struct  adapters
 
struct  cidinfo
 
struct  devices
 
struct  hfp_ag
 This struct holds HFP features the AG supports. More...
 
struct  hfp_cind
 This struct holds mappings for indications. More...
 
struct  hfp_hf
 This struct holds HFP features that we support. More...
 
struct  hfp_pvt
 This struct holds state information about the current hfp connection. More...
 
struct  mbl_pvt
 
struct  mbl_pvt::msg_queue
 
struct  msg_queue_entry
 

Macros

#define CHANNEL_FRAME_SIZE   320
 
#define DEVICE_FRAME_FORMAT   ast_format_slin
 
#define DEVICE_FRAME_SIZE   48
 
#define FORMAT1   "%-15.15s %-17.17s %-5.5s %-15.15s %-9.9s %-10.10s %-3.3s\n"
 
#define FORMAT1   "%-17.17s %-30.30s %-6.6s %-7.7s %-4.4s\n"
 
#define FORMAT2   "%-17.17s %-30.30s %-6.6s %-7.7s %d\n"
 
#define HFP_AG_CONTROL   (1 << 7)
 
#define HFP_AG_CW   (1 << 0)
 
#define HFP_AG_ECNR   (1 << 1)
 
#define HFP_AG_ERRORS   (1 << 8)
 
#define HFP_AG_REJECT   (1 << 5)
 
#define HFP_AG_RING   (1 << 3)
 
#define HFP_AG_STATUS   (1 << 6)
 
#define HFP_AG_TAG   (1 << 4)
 
#define HFP_AG_VOICE   (1 << 2)
 
#define HFP_CIND_BATTCHG   7
 
#define HFP_CIND_CALL   2
 
#define HFP_CIND_CALL_ACTIVE   1
 
#define HFP_CIND_CALL_NONE   0
 
#define HFP_CIND_CALLHELD   4
 
#define HFP_CIND_CALLSETUP   3
 
#define HFP_CIND_CALLSETUP_ALERTING   3
 
#define HFP_CIND_CALLSETUP_INCOMING   1
 
#define HFP_CIND_CALLSETUP_NONE   0
 
#define HFP_CIND_CALLSETUP_OUTGOING   2
 
#define HFP_CIND_NONE   0
 
#define HFP_CIND_ROAM   6
 
#define HFP_CIND_SERVICE   1
 
#define HFP_CIND_SERVICE_AVAILABLE   1
 
#define HFP_CIND_SERVICE_NONE   0
 
#define HFP_CIND_SIGNAL   5
 
#define HFP_CIND_UNKNOWN   -1
 
#define HFP_HF_CID   (1 << 2)
 
#define HFP_HF_CONTROL   (1 << 6)
 
#define HFP_HF_CW   (1 << 1)
 
#define HFP_HF_ECNR   (1 << 0)
 
#define HFP_HF_STATUS   (1 << 5)
 
#define HFP_HF_VOICE   (1 << 3)
 
#define HFP_HF_VOLUME   (1 << 4)
 
#define MBL_CONFIG   "chan_mobile.conf"
 
#define MBL_CONFIG_OLD   "mobile.conf"
 
#define rfcomm_read_debug(c)
 

Enumerations

enum  at_message_t {
  AT_PARSE_ERROR = -2, AT_READ_ERROR = -1, AT_UNKNOWN = 0, AT_OK,
  AT_ERROR, AT_RING, AT_BRSF, AT_CIND,
  AT_CIEV, AT_CLIP, AT_CMTI, AT_CMGR,
  AT_SMS_PROMPT, AT_CMS_ERROR, AT_A, AT_D,
  AT_CHUP, AT_CKPD, AT_CMGS, AT_VGM,
  AT_VGS, AT_VTS, AT_CMGF, AT_CNMI,
  AT_CMER, AT_CIND_TEST, AT_CUSD, AT_BUSY,
  AT_NO_DIALTONE, AT_NO_CARRIER, AT_ECAM
}
 
enum  mbl_type { MBL_TYPE_PHONE, MBL_TYPE_HEADSET }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int at_match_prefix (char *buf, char *prefix)
 Match the given buffer with the given prefix. More...
 
static const char * at_msg2str (at_message_t msg)
 Get the string representation of the given AT message. More...
 
static at_message_t at_read_full (int rsock, char *buf, size_t count)
 Read an AT message and clasify it. More...
 
static int check_unloading ()
 Check if the module is unloading. More...
 
static void do_alignment_detection (struct mbl_pvt *pvt, char *buf, int buflen)
 
static void * do_discovery (void *data)
 
static void * do_monitor_headset (void *data)
 
static void * do_monitor_phone (void *data)
 
static void * do_sco_listen (void *data)
 Service new and existing SCO connections. This thread accepts new sco connections and handles audio data. There is one do_sco_listen thread for each adapter. More...
 
static char * handle_cli_mobile_cusd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_mobile_rfcomm (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_mobile_search (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_mobile_show_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_response_brsf (struct mbl_pvt *pvt, char *buf)
 Handle the BRSF response. More...
 
static int handle_response_busy (struct mbl_pvt *pvt)
 Handle BUSY messages. More...
 
static int handle_response_ciev (struct mbl_pvt *pvt, char *buf)
 Handle AT+CIEV messages. More...
 
static int handle_response_cind (struct mbl_pvt *pvt, char *buf)
 Handle the CIND response. More...
 
static int handle_response_clip (struct mbl_pvt *pvt, char *buf)
 Handle AT+CLIP messages. More...
 
static int handle_response_cmgr (struct mbl_pvt *pvt, char *buf)
 Handle AT+CMGR messages. More...
 
static int handle_response_cmti (struct mbl_pvt *pvt, char *buf)
 Handle AT+CMTI messages. More...
 
static int handle_response_cusd (struct mbl_pvt *pvt, char *buf)
 Handle CUSD messages. More...
 
static int handle_response_error (struct mbl_pvt *pvt, char *buf)
 Handle ERROR AT messages. More...
 
static int handle_response_no_carrier (struct mbl_pvt *pvt, char *buf)
 Handle NO CARRIER messages. More...
 
static int handle_response_no_dialtone (struct mbl_pvt *pvt, char *buf)
 Handle NO DIALTONE messages. More...
 
static int handle_response_ok (struct mbl_pvt *pvt, char *buf)
 Handle OK AT messages. More...
 
static int handle_response_ring (struct mbl_pvt *pvt, char *buf)
 Handle RING messages. More...
 
static int handle_sms_prompt (struct mbl_pvt *pvt, char *buf)
 Send an SMS message from the queue. More...
 
static int headset_send_ring (const void *data)
 
static int hfp_brsf2int (struct hfp_hf *hf)
 Convert a hfp_hf struct to a BRSF int. More...
 
static struct hfp_aghfp_int2brsf (int brsf, struct hfp_ag *ag)
 Convert a BRSF int to an hfp_ag struct. More...
 
static int hfp_parse_brsf (struct hfp_pvt *hfp, const char *buf)
 Parse BRSF data. More...
 
static int hfp_parse_ciev (struct hfp_pvt *hfp, char *buf, int *value)
 Parse a CIEV event. More...
 
static int hfp_parse_cind (struct hfp_pvt *hfp, char *buf)
 Read the result of the AT+CIND? command. More...
 
static int hfp_parse_cind_indicator (struct hfp_pvt *hfp, int group, char *indicator)
 Parse and store the given indicator. More...
 
static int hfp_parse_cind_test (struct hfp_pvt *hfp, char *buf)
 Parse the result of the AT+CIND=? command. More...
 
static struct cidinfo hfp_parse_clip (struct hfp_pvt *hfp, char *buf)
 Parse a CLIP event. More...
 
static int hfp_parse_cmgr (struct hfp_pvt *hfp, char *buf, char **from_number, char **text)
 Parse a CMGR message. More...
 
static int hfp_parse_cmti (struct hfp_pvt *hfp, char *buf)
 Parse a CMTI notification. More...
 
static char * hfp_parse_cusd (struct hfp_pvt *hfp, char *buf)
 Parse a CUSD answer. More...
 
static int hfp_parse_ecav (struct hfp_pvt *hfp, char *buf)
 Parse a ECAV event. More...
 
static int hfp_send_ata (struct hfp_pvt *hfp)
 Send ATA. More...
 
static int hfp_send_atd (struct hfp_pvt *hfp, const char *number)
 Send ATD. More...
 
static int hfp_send_brsf (struct hfp_pvt *hfp, struct hfp_hf *brsf)
 Send a BRSF request. More...
 
static int hfp_send_chup (struct hfp_pvt *hfp)
 Send AT+CHUP. More...
 
static int hfp_send_cind (struct hfp_pvt *hfp)
 Send the CIND read command. More...
 
static int hfp_send_cind_test (struct hfp_pvt *hfp)
 Send the CIND test command. More...
 
static int hfp_send_clip (struct hfp_pvt *hfp, int status)
 Enable or disable calling line identification. More...
 
static int hfp_send_cmer (struct hfp_pvt *hfp, int status)
 Enable or disable indicator events reporting. More...
 
static int hfp_send_cmgf (struct hfp_pvt *hfp, int mode)
 Set the SMS mode. More...
 
static int hfp_send_cmgr (struct hfp_pvt *hfp, int index)
 Read an SMS message. More...
 
static int hfp_send_cmgs (struct hfp_pvt *hfp, const char *number)
 Start sending an SMS message. More...
 
static int hfp_send_cnmi (struct hfp_pvt *hfp)
 Setup SMS new message indication. More...
 
static int hfp_send_cusd (struct hfp_pvt *hfp, const char *code)
 Send CUSD. More...
 
static int hfp_send_dtmf (struct hfp_pvt *hfp, char digit)
 Send a DTMF command. More...
 
static int hfp_send_ecam (struct hfp_pvt *hfp)
 Enable Sony Erricson extensions / indications. More...
 
static int hfp_send_sms_text (struct hfp_pvt *hfp, const char *message)
 Send the text of an SMS message. More...
 
static int hfp_send_vgs (struct hfp_pvt *hfp, int value)
 Send the current speaker gain level. More...
 
static int hsp_send_error (int rsock)
 Send an ERROR AT response. More...
 
static int hsp_send_ok (int rsock)
 Send an OK AT response. More...
 
static int hsp_send_ring (int rsock)
 Send a RING unsolicited AT response. More...
 
static int hsp_send_vgm (int rsock, int gain)
 Send a microphone gain unsolicited AT response. More...
 
static int hsp_send_vgs (int rsock, int gain)
 Send a speaker gain unsolicited AT response. More...
 
static int load_module (void)
 
static int mbl_answer (struct ast_channel *ast)
 
static int mbl_ast_hangup (struct mbl_pvt *pvt)
 
static int mbl_call (struct ast_channel *ast, const char *dest, int timeout)
 
static int mbl_devicestate (const char *data)
 
static int mbl_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
static int mbl_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
static int mbl_hangup (struct ast_channel *ast)
 
static int mbl_has_service (struct mbl_pvt *pvt)
 Check if a mobile device has service. More...
 
static struct adapter_pvtmbl_load_adapter (struct ast_config *cfg, const char *cat)
 Load an adapter from the configuration file. More...
 
static int mbl_load_config (void)
 
static struct mbl_pvtmbl_load_device (struct ast_config *cfg, const char *cat)
 Load a device from the configuration file. More...
 
static struct ast_channelmbl_new (int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
 
static int mbl_queue_control (struct mbl_pvt *pvt, enum ast_control_frame_type control)
 
static int mbl_queue_hangup (struct mbl_pvt *pvt)
 
static struct ast_framembl_read (struct ast_channel *ast)
 
static struct ast_channelmbl_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 mbl_sendsms_exec (struct ast_channel *ast, const char *data)
 
static int mbl_status_exec (struct ast_channel *ast, const char *data)
 
static int mbl_write (struct ast_channel *ast, struct ast_frame *frame)
 
static void msg_queue_flush (struct mbl_pvt *pvt)
 Remove all itmes from the queue and free them. More...
 
static void msg_queue_free_and_pop (struct mbl_pvt *pvt)
 Remove an item from the front of the queue, and free it. More...
 
static struct msg_queue_entrymsg_queue_head (struct mbl_pvt *pvt)
 Get the head of a queue. More...
 
static struct msg_queue_entrymsg_queue_pop (struct mbl_pvt *pvt)
 Remove an item from the front of the queue. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
static int rfcomm_connect (bdaddr_t src, bdaddr_t dst, int remote_channel)
 
static ssize_t rfcomm_read (int rsock, char *buf, size_t count)
 Read one Hayes AT message from an rfcomm socket. More...
 
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 character. More...
 
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. More...
 
static int rfcomm_read_cmgr (int rsock, char **buf, size_t count, size_t *in_count)
 Read the remainder of a +CMGR message. More...
 
static int rfcomm_read_command (int rsock, char **buf, size_t count, size_t *in_count)
 Read the remainder of an AT command. More...
 
static int rfcomm_read_result (int rsock, char **buf, size_t count, size_t *in_count)
 Read and AT result code. More...
 
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. More...
 
static int rfcomm_read_until_crlf (int rsock, char **buf, size_t count, size_t *in_count)
 Read until. More...
 
static int rfcomm_read_until_ok (int rsock, char **buf, size_t count, size_t *in_count)
 Read until a. More...
 
static int rfcomm_wait (int rsock, int *ms)
 Wait for activity on an rfcomm socket. More...
 
static int rfcomm_write (int rsock, char *buf)
 Write to an rfcomm socket. More...
 
static int rfcomm_write_full (int rsock, char *buf, size_t count)
 Write to an rfcomm socket. More...
 
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 audio connections. More...
 
static int sco_bind (struct adapter_pvt *adapter)
 Bind an SCO listener socket for the given adapter. More...
 
static int sco_connect (bdaddr_t src, bdaddr_t dst)
 
static int sco_write (int s, char *buf, int len)
 
static sdp_session_t * sdp_register (void)
 
static int sdp_search (char *addr, int profile)
 
static void set_unloading ()
 Set the unloading flag. More...
 
static int start_monitor (struct mbl_pvt *pvt)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Bluetooth Mobile Device Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
 
static struct adapters adapters = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static char * app_mblsendsms = "MobileSendSMS"
 
static char * app_mblstatus = "MobileStatus"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct devices devices = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int discovery_interval = 60
 
static pthread_t discovery_thread = AST_PTHREADT_NULL
 
static struct hfp_hf hfp_our_brsf
 
static struct ast_cli_entry mbl_cli []
 
static struct ast_channel_tech mbl_tech
 
static char * mblsendsms_desc
 
static char * mblsendsms_synopsis = "MobileSendSMS(Device,Dest,Message)"
 
static char * mblstatus_desc
 
static char * mblstatus_synopsis = "MobileStatus(Device,Variable)"
 
static sdp_session_t * sdp_session
 
static ast_mutex_t unload_mutex = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static int unloading_flag = 0
 

Detailed Description

Bluetooth Mobile Device channel driver.

Author
Dave Bowerman david.nosp@m..bow.nosp@m.erman.nosp@m.@gma.nosp@m.il.co.nosp@m.m

Definition in file chan_mobile.c.

Macro Definition Documentation

◆ CHANNEL_FRAME_SIZE

#define CHANNEL_FRAME_SIZE   320

Definition at line 83 of file chan_mobile.c.

Referenced by mbl_load_device(), and mbl_new().

◆ DEVICE_FRAME_FORMAT

#define DEVICE_FRAME_FORMAT   ast_format_slin

Definition at line 82 of file chan_mobile.c.

Referenced by load_module(), mbl_new(), mbl_read(), and mbl_request().

◆ DEVICE_FRAME_SIZE

#define DEVICE_FRAME_SIZE   48

Definition at line 81 of file chan_mobile.c.

Referenced by mbl_load_device(), mbl_new(), and mbl_read().

◆ FORMAT1 [1/2]

#define FORMAT1   "%-15.15s %-17.17s %-5.5s %-15.15s %-9.9s %-10.10s %-3.3s\n"

◆ FORMAT1 [2/2]

#define FORMAT1   "%-17.17s %-30.30s %-6.6s %-7.7s %-4.4s\n"

◆ FORMAT2

#define FORMAT2   "%-17.17s %-30.30s %-6.6s %-7.7s %d\n"

◆ HFP_AG_CONTROL

#define HFP_AG_CONTROL   (1 << 7)

Definition at line 272 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_CW

#define HFP_AG_CW   (1 << 0)

Definition at line 265 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_ECNR

#define HFP_AG_ECNR   (1 << 1)

Definition at line 266 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_ERRORS

#define HFP_AG_ERRORS   (1 << 8)

Definition at line 273 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_REJECT

#define HFP_AG_REJECT   (1 << 5)

Definition at line 270 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_RING

#define HFP_AG_RING   (1 << 3)

Definition at line 268 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_STATUS

#define HFP_AG_STATUS   (1 << 6)

Definition at line 271 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_TAG

#define HFP_AG_TAG   (1 << 4)

Definition at line 269 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_AG_VOICE

#define HFP_AG_VOICE   (1 << 2)

Definition at line 267 of file chan_mobile.c.

Referenced by hfp_int2brsf().

◆ HFP_CIND_BATTCHG

#define HFP_CIND_BATTCHG   7

Definition at line 283 of file chan_mobile.c.

Referenced by hfp_parse_cind_test().

◆ HFP_CIND_CALL

#define HFP_CIND_CALL   2

Definition at line 278 of file chan_mobile.c.

Referenced by handle_response_ciev(), and hfp_parse_cind_test().

◆ HFP_CIND_CALL_ACTIVE

#define HFP_CIND_CALL_ACTIVE   1

Definition at line 287 of file chan_mobile.c.

Referenced by handle_response_ciev().

◆ HFP_CIND_CALL_NONE

#define HFP_CIND_CALL_NONE   0

Definition at line 286 of file chan_mobile.c.

Referenced by handle_response_ciev().

◆ HFP_CIND_CALLHELD

#define HFP_CIND_CALLHELD   4

Definition at line 280 of file chan_mobile.c.

Referenced by hfp_parse_cind_test().

◆ HFP_CIND_CALLSETUP

#define HFP_CIND_CALLSETUP   3

Definition at line 279 of file chan_mobile.c.

Referenced by handle_response_ciev(), and hfp_parse_cind_test().

◆ HFP_CIND_CALLSETUP_ALERTING

#define HFP_CIND_CALLSETUP_ALERTING   3

Definition at line 293 of file chan_mobile.c.

Referenced by handle_response_ciev().

◆ HFP_CIND_CALLSETUP_INCOMING

#define HFP_CIND_CALLSETUP_INCOMING   1

Definition at line 291 of file chan_mobile.c.

Referenced by handle_response_ciev().

◆ HFP_CIND_CALLSETUP_NONE

#define HFP_CIND_CALLSETUP_NONE   0

Definition at line 290 of file chan_mobile.c.

Referenced by handle_response_ciev().

◆ HFP_CIND_CALLSETUP_OUTGOING

#define HFP_CIND_CALLSETUP_OUTGOING   2

Definition at line 292 of file chan_mobile.c.

Referenced by handle_response_ciev().

◆ HFP_CIND_NONE

#define HFP_CIND_NONE   0

Definition at line 276 of file chan_mobile.c.

Referenced by handle_response_ciev(), and hfp_parse_ciev().

◆ HFP_CIND_ROAM

#define HFP_CIND_ROAM   6

Definition at line 282 of file chan_mobile.c.

Referenced by hfp_parse_cind_test().

◆ HFP_CIND_SERVICE

#define HFP_CIND_SERVICE   1

Definition at line 277 of file chan_mobile.c.

Referenced by hfp_parse_cind_test().

◆ HFP_CIND_SERVICE_AVAILABLE

#define HFP_CIND_SERVICE_AVAILABLE   1

Definition at line 297 of file chan_mobile.c.

Referenced by mbl_has_service().

◆ HFP_CIND_SERVICE_NONE

#define HFP_CIND_SERVICE_NONE   0

Definition at line 296 of file chan_mobile.c.

◆ HFP_CIND_SIGNAL

#define HFP_CIND_SIGNAL   5

Definition at line 281 of file chan_mobile.c.

Referenced by hfp_parse_cind_test().

◆ HFP_CIND_UNKNOWN

#define HFP_CIND_UNKNOWN   -1

Definition at line 275 of file chan_mobile.c.

Referenced by hfp_parse_cind_test().

◆ HFP_HF_CID

#define HFP_HF_CID   (1 << 2)

Definition at line 259 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ HFP_HF_CONTROL

#define HFP_HF_CONTROL   (1 << 6)

Definition at line 263 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ HFP_HF_CW

#define HFP_HF_CW   (1 << 1)

Definition at line 258 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ HFP_HF_ECNR

#define HFP_HF_ECNR   (1 << 0)

Definition at line 257 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ HFP_HF_STATUS

#define HFP_HF_STATUS   (1 << 5)

Definition at line 262 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ HFP_HF_VOICE

#define HFP_HF_VOICE   (1 << 3)

Definition at line 260 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ HFP_HF_VOLUME

#define HFP_HF_VOLUME   (1 << 4)

Definition at line 261 of file chan_mobile.c.

Referenced by hfp_brsf2int().

◆ MBL_CONFIG

#define MBL_CONFIG   "chan_mobile.conf"

Definition at line 78 of file chan_mobile.c.

Referenced by load_module(), and mbl_load_config().

◆ MBL_CONFIG_OLD

#define MBL_CONFIG_OLD   "mobile.conf"

Definition at line 79 of file chan_mobile.c.

Referenced by mbl_load_config().

◆ rfcomm_read_debug

#define rfcomm_read_debug (   c)

Enumeration Type Documentation

◆ at_message_t

Enumerator
AT_PARSE_ERROR 
AT_READ_ERROR 
AT_UNKNOWN 
AT_OK 
AT_ERROR 
AT_RING 
AT_BRSF 
AT_CIND 
AT_CIEV 
AT_CLIP 
AT_CMTI 
AT_CMGR 
AT_SMS_PROMPT 
AT_CMS_ERROR 
AT_A 
AT_D 
AT_CHUP 
AT_CKPD 
AT_CMGS 
AT_VGM 
AT_VGS 
AT_VTS 
AT_CMGF 
AT_CNMI 
AT_CMER 
AT_CIND_TEST 
AT_CUSD 
AT_BUSY 
AT_NO_DIALTONE 
AT_NO_CARRIER 
AT_ECAM 

Definition at line 419 of file chan_mobile.c.

419  {
420  /* errors */
421  AT_PARSE_ERROR = -2,
422  AT_READ_ERROR = -1,
423  AT_UNKNOWN = 0,
424  /* at responses */
425  AT_OK,
426  AT_ERROR,
427  AT_RING,
428  AT_BRSF,
429  AT_CIND,
430  AT_CIEV,
431  AT_CLIP,
432  AT_CMTI,
433  AT_CMGR,
435  AT_CMS_ERROR,
436  /* at commands */
437  AT_A,
438  AT_D,
439  AT_CHUP,
440  AT_CKPD,
441  AT_CMGS,
442  AT_VGM,
443  AT_VGS,
444  AT_VTS,
445  AT_CMGF,
446  AT_CNMI,
447  AT_CMER,
448  AT_CIND_TEST,
449  AT_CUSD,
450  AT_BUSY,
453  AT_ECAM,
454 } at_message_t;
at_message_t
Definition: chan_mobile.c:419

◆ mbl_type

enum mbl_type
Enumerator
MBL_TYPE_PHONE 
MBL_TYPE_HEADSET 

Definition at line 94 of file chan_mobile.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4838 of file chan_mobile.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4838 of file chan_mobile.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 4838 of file chan_mobile.c.

◆ at_match_prefix()

static int at_match_prefix ( char *  buf,
char *  prefix 
)
static

Match the given buffer with the given prefix.

Parameters
bufthe buffer to match
prefixthe prefix to match

Definition at line 2003 of file chan_mobile.c.

Referenced by at_read_full().

2004 {
2005  return !strncmp(buf, prefix, strlen(prefix));
2006 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ at_msg2str()

static const char * at_msg2str ( at_message_t  msg)
inlinestatic

Get the string representation of the given AT message.

Parameters
msgthe message to process
Returns
a string describing the given message

Definition at line 2076 of file chan_mobile.c.

References AT_A, AT_BRSF, AT_BUSY, AT_CHUP, AT_CIEV, AT_CIND, AT_CIND_TEST, AT_CKPD, AT_CLIP, AT_CMER, AT_CMGF, AT_CMGR, AT_CMGS, AT_CMS_ERROR, AT_CMTI, AT_CNMI, AT_CUSD, AT_D, AT_ECAM, AT_ERROR, AT_NO_CARRIER, AT_NO_DIALTONE, AT_OK, AT_PARSE_ERROR, AT_READ_ERROR, AT_RING, AT_SMS_PROMPT, AT_UNKNOWN, AT_VGM, AT_VGS, and AT_VTS.

Referenced by do_monitor_headset(), do_monitor_phone(), handle_response_brsf(), handle_response_cind(), handle_response_error(), and handle_response_ok().

2077 {
2078  switch (msg) {
2079  /* errors */
2080  case AT_PARSE_ERROR:
2081  return "PARSE ERROR";
2082  case AT_READ_ERROR:
2083  return "READ ERROR";
2084  default:
2085  case AT_UNKNOWN:
2086  return "UNKNOWN";
2087  /* at responses */
2088  case AT_OK:
2089  return "OK";
2090  case AT_ERROR:
2091  return "ERROR";
2092  case AT_RING:
2093  return "RING";
2094  case AT_BRSF:
2095  return "AT+BRSF";
2096  case AT_CIND:
2097  return "AT+CIND";
2098  case AT_CIEV:
2099  return "AT+CIEV";
2100  case AT_CLIP:
2101  return "AT+CLIP";
2102  case AT_CMTI:
2103  return "AT+CMTI";
2104  case AT_CMGR:
2105  return "AT+CMGR";
2106  case AT_SMS_PROMPT:
2107  return "SMS PROMPT";
2108  case AT_CMS_ERROR:
2109  return "+CMS ERROR";
2110  case AT_BUSY:
2111  return "BUSY";
2112  case AT_NO_DIALTONE:
2113  return "NO DIALTONE";
2114  case AT_NO_CARRIER:
2115  return "NO CARRIER";
2116  /* at commands */
2117  case AT_A:
2118  return "ATA";
2119  case AT_D:
2120  return "ATD";
2121  case AT_CHUP:
2122  return "AT+CHUP";
2123  case AT_CKPD:
2124  return "AT+CKPD";
2125  case AT_CMGS:
2126  return "AT+CMGS";
2127  case AT_VGM:
2128  return "AT+VGM";
2129  case AT_VGS:
2130  return "AT+VGS";
2131  case AT_VTS:
2132  return "AT+VTS";
2133  case AT_CMGF:
2134  return "AT+CMGF";
2135  case AT_CNMI:
2136  return "AT+CNMI";
2137  case AT_CMER:
2138  return "AT+CMER";
2139  case AT_CIND_TEST:
2140  return "AT+CIND=?";
2141  case AT_CUSD:
2142  return "AT+CUSD";
2143  case AT_ECAM:
2144  return "AT*ECAM";
2145  }
2146 }

◆ at_read_full()

static at_message_t at_read_full ( int  rsock,
char *  buf,
size_t  count 
)
static

Read an AT message and clasify it.

Parameters
rsockan rfcomm socket
bufthe buffer to store the result in
countthe size of the buffer or the maximum number of characters to read
Returns
the type of message received, in addition buf will contain the message received and will be null terminated
See also
at_read()

Definition at line 2017 of file chan_mobile.c.

References AT_BRSF, AT_BUSY, AT_CIEV, AT_CIND, AT_CKPD, AT_CLIP, AT_CMGR, AT_CMS_ERROR, AT_CMTI, AT_CUSD, AT_ECAM, AT_ERROR, at_match_prefix(), AT_NO_CARRIER, AT_NO_DIALTONE, AT_OK, AT_RING, AT_SMS_PROMPT, AT_UNKNOWN, AT_VGM, AT_VGS, and rfcomm_read().

Referenced by do_monitor_headset(), and do_monitor_phone().

2018 {
2019  ssize_t s;
2020  if ((s = rfcomm_read(rsock, buf, count - 1)) < 1)
2021  return s;
2022  buf[s] = '\0';
2023 
2024  if (!strcmp("OK", buf)) {
2025  return AT_OK;
2026  } else if (!strcmp("ERROR", buf)) {
2027  return AT_ERROR;
2028  } else if (!strcmp("RING", buf)) {
2029  return AT_RING;
2030  } else if (!strcmp("AT+CKPD=200", buf)) {
2031  return AT_CKPD;
2032  } else if (!strcmp("> ", buf)) {
2033  return AT_SMS_PROMPT;
2034  } else if (at_match_prefix(buf, "+CMTI:")) {
2035  return AT_CMTI;
2036  } else if (at_match_prefix(buf, "+CIEV:")) {
2037  return AT_CIEV;
2038  } else if (at_match_prefix(buf, "+BRSF:")) {
2039  return AT_BRSF;
2040  } else if (at_match_prefix(buf, "+CIND:")) {
2041  return AT_CIND;
2042  } else if (at_match_prefix(buf, "+CLIP:")) {
2043  return AT_CLIP;
2044  } else if (at_match_prefix(buf, "+CMGR:")) {
2045  return AT_CMGR;
2046  } else if (at_match_prefix(buf, "+VGM:")) {
2047  return AT_VGM;
2048  } else if (at_match_prefix(buf, "+VGS:")) {
2049  return AT_VGS;
2050  } else if (at_match_prefix(buf, "+CMS ERROR:")) {
2051  return AT_CMS_ERROR;
2052  } else if (at_match_prefix(buf, "AT+VGM=")) {
2053  return AT_VGM;
2054  } else if (at_match_prefix(buf, "AT+VGS=")) {
2055  return AT_VGS;
2056  } else if (at_match_prefix(buf, "+CUSD:")) {
2057  return AT_CUSD;
2058  } else if (at_match_prefix(buf, "BUSY")) {
2059  return AT_BUSY;
2060  } else if (at_match_prefix(buf, "NO DIALTONE")) {
2061  return AT_NO_DIALTONE;
2062  } else if (at_match_prefix(buf, "NO CARRIER")) {
2063  return AT_NO_CARRIER;
2064  } else if (at_match_prefix(buf, "*ECAV:")) {
2065  return AT_ECAM;
2066  } else {
2067  return AT_UNKNOWN;
2068  }
2069 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int at_match_prefix(char *buf, char *prefix)
Match the given buffer with the given prefix.
Definition: chan_mobile.c:2003
static ssize_t rfcomm_read(int rsock, char *buf, size_t count)
Read one Hayes AT message from an rfcomm socket.
Definition: chan_mobile.c:1808

◆ check_unloading()

static int check_unloading ( )
inlinestatic

Check if the module is unloading.

Return values
0not unloading
1unloading

Definition at line 4682 of file chan_mobile.c.

References ast_mutex_lock, ast_mutex_unlock, unload_mutex, and unloading_flag.

Referenced by do_discovery(), do_monitor_headset(), do_monitor_phone(), and do_sco_listen().

4683 {
4684  int res;
4686  res = unloading_flag;
4688 
4689  return res;
4690 }
static int unloading_flag
Definition: chan_mobile.c:90
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t unload_mutex
Definition: chan_mobile.c:89
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ do_alignment_detection()

static void do_alignment_detection ( struct mbl_pvt pvt,
char *  buf,
int  buflen 
)
static

Definition at line 1281 of file chan_mobile.c.

References a, abs, mbl_pvt::alignment_count, mbl_pvt::alignment_detection_triggered, mbl_pvt::alignment_samples, ast_debug, and mbl_pvt::do_alignment_detection.

Referenced by mbl_read().

1282 {
1283 
1284  int i;
1285  short a, *s;
1286  char *p;
1287 
1288  if (pvt->alignment_detection_triggered) {
1289  for (i=buflen, p=buf+buflen-1; i>0; i--, p--)
1290  *p = *(p-1);
1291  *(p+1) = 0;
1292  return;
1293  }
1294 
1295  if (pvt->alignment_count < 4) {
1296  s = (short *)buf;
1297  for (i=0, a=0; i<buflen/2; i++) {
1298  a += *s++;
1299  a /= i+1;
1300  }
1301  pvt->alignment_samples[pvt->alignment_count++] = a;
1302  return;
1303  }
1304 
1305  ast_debug(1, "Alignment Detection result is [%-d %-d %-d %-d]\n", pvt->alignment_samples[0], pvt->alignment_samples[1], pvt->alignment_samples[2], pvt->alignment_samples[3]);
1306 
1307  a = abs(pvt->alignment_samples[1]) + abs(pvt->alignment_samples[2]) + abs(pvt->alignment_samples[3]);
1308  a /= 3;
1309  if (a > 100) {
1311  ast_debug(1, "Alignment Detection Triggered.\n");
1312  } else
1313  pvt->do_alignment_detection = 0;
1314 
1315 }
int alignment_count
Definition: chan_mobile.c:146
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
unsigned int do_alignment_detection
Definition: chan_mobile.c:142
short alignment_samples[4]
Definition: chan_mobile.c:145
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
unsigned int alignment_detection_triggered
Definition: chan_mobile.c:143
#define abs(x)
Definition: f2c.h:195
static struct test_val a

◆ do_discovery()

static void* do_discovery ( void *  data)
static

Definition at line 4282 of file chan_mobile.c.

References mbl_pvt::adapter, adapter_pvt::addr, mbl_pvt::addr, ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_verb, check_unloading(), mbl_pvt::connected, discovery_interval, EVENT_FLAG_SYSTEM, adapter_pvt::id, mbl_pvt::id, adapter_pvt::inuse, mbl_pvt::lock, manager_event, NULL, rfcomm_connect(), mbl_pvt::rfcomm_port, mbl_pvt::rfcomm_socket, and start_monitor().

Referenced by load_module().

4283 {
4284 
4285  struct adapter_pvt *adapter;
4286  struct mbl_pvt *pvt;
4287 
4288  while (!check_unloading()) {
4290  AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
4291  if (!adapter->inuse) {
4294  ast_mutex_lock(&pvt->lock);
4295  if (!adapter->inuse && !pvt->connected && !strcmp(adapter->id, pvt->adapter->id)) {
4296  if ((pvt->rfcomm_socket = rfcomm_connect(adapter->addr, pvt->addr, pvt->rfcomm_port)) > -1) {
4297  if (start_monitor(pvt)) {
4298  pvt->connected = 1;
4299  adapter->inuse = 1;
4300  manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Connect\r\nDevice: %s\r\n", pvt->id);
4301  ast_verb(3, "Bluetooth Device %s has connected, initializing...\n", pvt->id);
4302  }
4303  }
4304  }
4305  ast_mutex_unlock(&pvt->lock);
4306  }
4308  }
4309  }
4311 
4312 
4313  /* Go to sleep (only if we are not unloading) */
4314  if (!check_unloading())
4315  sleep(discovery_interval);
4316  }
4317 
4318  return NULL;
4319 }
int rfcomm_port
Definition: chan_mobile.c:131
char id[31]
Definition: chan_mobile.c:102
static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel)
Definition: chan_mobile.c:1390
unsigned int connected
Definition: chan_mobile.c:161
static int check_unloading(void)
Check if the module is unloading.
Definition: chan_mobile.c:4682
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
unsigned int inuse
Definition: chan_mobile.c:104
#define NULL
Definition: resample.c:96
int rfcomm_socket
Definition: chan_mobile.c:132
#define ast_verb(level,...)
Definition: logger.h:463
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
bdaddr_t addr
Definition: chan_mobile.c:127
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static int discovery_interval
Definition: chan_mobile.c:85
char id[31]
Definition: chan_mobile.c:125
static int start_monitor(struct mbl_pvt *pvt)
Definition: chan_mobile.c:4261
ast_mutex_t lock
Definition: chan_mobile.c:121
bdaddr_t addr
Definition: chan_mobile.c:103
struct adapter_pvt * adapter
Definition: chan_mobile.c:128
Definition: search.h:40
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ do_monitor_headset()

static void* do_monitor_headset ( void *  data)
static

Definition at line 4119 of file chan_mobile.c.

References mbl_pvt::adapter, adapter_pvt::addr, mbl_pvt::addr, mbl_pvt::answered, ast_channel_exten_set(), ast_channel_set_fd(), AST_CONTROL_ANSWER, ast_debug, ast_hangup(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), ast_sched_runq(), ast_sched_wait(), AST_STATE_UP, ast_verb, AT_CKPD, at_msg2str(), at_read_full(), AT_VGM, AT_VGS, buf, check_unloading(), mbl_pvt::connected, errno, EVENT_FLAG_SYSTEM, hsp_send_error(), hsp_send_ok(), hsp_send_vgm(), hsp_send_vgs(), mbl_pvt::id, mbl_pvt::incoming, adapter_pvt::inuse, mbl_pvt::lock, LOG_ERROR, manager_event, mbl_new(), mbl_queue_control(), mbl_queue_hangup(), mbl_pvt::needring, NULL, mbl_pvt::outgoing, mbl_pvt::owner, mbl_pvt::rfcomm_socket, rfcomm_wait(), mbl_pvt::sched, sco_connect(), and mbl_pvt::sco_socket.

Referenced by start_monitor().

4120 {
4121 
4122  struct mbl_pvt *pvt = (struct mbl_pvt *)data;
4123  char buf[256];
4124  int t;
4125  at_message_t at_msg;
4126  struct ast_channel *chan = NULL;
4127 
4128  ast_verb(3, "Bluetooth Device %s initialised and ready.\n", pvt->id);
4129 
4130  while (!check_unloading()) {
4131 
4132  t = ast_sched_wait(pvt->sched);
4133  if (t == -1) {
4134  t = 6000;
4135  }
4136 
4137  ast_sched_runq(pvt->sched);
4138 
4139  if (rfcomm_wait(pvt->rfcomm_socket, &t) == 0)
4140  continue;
4141 
4142  if ((at_msg = at_read_full(pvt->rfcomm_socket, buf, sizeof(buf))) < 0) {
4143  ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
4144  goto e_cleanup;
4145  }
4146  ast_debug(1, "[%s] %s\n", pvt->id, buf);
4147 
4148  switch (at_msg) {
4149  case AT_VGS:
4150  case AT_VGM:
4151  /* XXX volume change requested, we will just
4152  * pretend to do something with it */
4153  if (hsp_send_ok(pvt->rfcomm_socket)) {
4154  ast_debug(1, "[%s] error sending AT message 'OK'\n", pvt->id);
4155  goto e_cleanup;
4156  }
4157  break;
4158  case AT_CKPD:
4159  ast_mutex_lock(&pvt->lock);
4160  if (pvt->outgoing) {
4161  pvt->needring = 0;
4162  hsp_send_ok(pvt->rfcomm_socket);
4163  if (pvt->answered) {
4164  /* we have an answered call up to the
4165  * HS, he wants to hangup */
4166  mbl_queue_hangup(pvt);
4167  } else {
4168  /* we have an outgoing call to the HS,
4169  * he wants to answer */
4170  if ((pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr)) == -1) {
4171  ast_log(LOG_ERROR, "[%s] unable to create audio connection\n", pvt->id);
4172  mbl_queue_hangup(pvt);
4173  ast_mutex_unlock(&pvt->lock);
4174  goto e_cleanup;
4175  }
4176 
4177  ast_channel_set_fd(pvt->owner, 0, pvt->sco_socket);
4178 
4180  pvt->answered = 1;
4181 
4182  if (hsp_send_vgs(pvt->rfcomm_socket, 13) || hsp_send_vgm(pvt->rfcomm_socket, 13)) {
4183  ast_debug(1, "[%s] error sending VGS/VGM\n", pvt->id);
4184  mbl_queue_hangup(pvt);
4185  ast_mutex_unlock(&pvt->lock);
4186  goto e_cleanup;
4187  }
4188  }
4189  } else if (pvt->incoming) {
4190  /* we have an incoming call from the
4191  * HS, he wants to hang up */
4192  mbl_queue_hangup(pvt);
4193  } else {
4194  /* no call is up, HS wants to dial */
4195  hsp_send_ok(pvt->rfcomm_socket);
4196 
4197  if ((pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr)) == -1) {
4198  ast_log(LOG_ERROR, "[%s] unable to create audio connection\n", pvt->id);
4199  ast_mutex_unlock(&pvt->lock);
4200  goto e_cleanup;
4201  }
4202 
4203  pvt->incoming = 1;
4204 
4205  if (!(chan = mbl_new(AST_STATE_UP, pvt, NULL, NULL, NULL))) {
4206  ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);
4207  ast_mutex_unlock(&pvt->lock);
4208  goto e_cleanup;
4209  }
4210 
4211  ast_channel_set_fd(chan, 0, pvt->sco_socket);
4212 
4213  ast_channel_exten_set(chan, "s");
4214  if (ast_pbx_start(chan)) {
4215  ast_log(LOG_ERROR, "[%s] unable to start pbx on incoming call\n", pvt->id);
4216  ast_hangup(chan);
4217  ast_mutex_unlock(&pvt->lock);
4218  goto e_cleanup;
4219  }
4220  }
4221  ast_mutex_unlock(&pvt->lock);
4222  break;
4223  default:
4224  ast_debug(1, "[%s] received unknown AT command: %s (%s)\n", pvt->id, buf, at_msg2str(at_msg));
4225  if (hsp_send_error(pvt->rfcomm_socket)) {
4226  ast_debug(1, "[%s] error sending AT message 'ERROR'\n", pvt->id);
4227  goto e_cleanup;
4228  }
4229  break;
4230  }
4231  }
4232 
4233 e_cleanup:
4234  ast_mutex_lock(&pvt->lock);
4235  if (pvt->owner) {
4236  ast_debug(1, "[%s] device disconnected, hanging up owner\n", pvt->id);
4237  mbl_queue_hangup(pvt);
4238  }
4239 
4240 
4241  close(pvt->rfcomm_socket);
4242  close(pvt->sco_socket);
4243  pvt->sco_socket = -1;
4244 
4245  pvt->connected = 0;
4246 
4247  pvt->needring = 0;
4248  pvt->outgoing = 0;
4249  pvt->incoming = 0;
4250 
4251  pvt->adapter->inuse = 0;
4252  ast_mutex_unlock(&pvt->lock);
4253 
4254  manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
4255  ast_verb(3, "Bluetooth Device %s has disconnected\n", pvt->id);
4256 
4257  return NULL;
4258 
4259 }
static int mbl_queue_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1334
Main Channel structure associated with a channel.
int sco_socket
Definition: chan_mobile.c:137
static int sco_connect(bdaddr_t src, bdaddr_t dst)
Definition: chan_mobile.c:1833
static int rfcomm_wait(int rsock, int *ms)
Wait for activity on an rfcomm socket.
Definition: chan_mobile.c:1479
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
unsigned int connected
Definition: chan_mobile.c:161
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
unsigned int answered
Definition: chan_mobile.c:160
static int check_unloading(void)
Check if the module is unloading.
Definition: chan_mobile.c:4682
static int hsp_send_vgs(int rsock, int gain)
Send a speaker gain unsolicited AT response.
Definition: chan_mobile.c:2943
#define ast_mutex_lock(a)
Definition: lock.h:187
unsigned int inuse
Definition: chan_mobile.c:104
#define NULL
Definition: resample.c:96
int rfcomm_socket
Definition: chan_mobile.c:132
static int hsp_send_error(int rsock)
Send an ERROR AT response.
Definition: chan_mobile.c:2933
unsigned int incoming
Definition: chan_mobile.c:154
#define ast_verb(level,...)
Definition: logger.h:463
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
bdaddr_t addr
Definition: chan_mobile.c:127
static int hsp_send_vgm(int rsock, int gain)
Send a microphone gain unsolicited AT response.
Definition: chan_mobile.c:2955
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
#define LOG_ERROR
Definition: logger.h:285
struct ast_channel * owner
Definition: chan_mobile.c:119
char id[31]
Definition: chan_mobile.c:125
int errno
ast_mutex_t lock
Definition: chan_mobile.c:121
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
bdaddr_t addr
Definition: chan_mobile.c:103
static int hsp_send_ok(int rsock)
Send an OK AT response.
Definition: chan_mobile.c:2924
static at_message_t at_read_full(int rsock, char *buf, size_t count)
Read an AT message and clasify it.
Definition: chan_mobile.c:2017
at_message_t
Definition: chan_mobile.c:419
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
unsigned int outgoing
Definition: chan_mobile.c:153
struct adapter_pvt * adapter
Definition: chan_mobile.c:128
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
unsigned int needring
Definition: chan_mobile.c:159
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
struct ast_sched_context * sched
Definition: chan_mobile.c:149
static struct ast_channel * mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_mobile.c:847
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ do_monitor_phone()

static void* do_monitor_phone ( void *  data)
static

Definition at line 3870 of file chan_mobile.c.

References mbl_pvt::adapter, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_verb, AT_BRSF, AT_BUSY, AT_CIEV, AT_CIND, AT_CIND_TEST, AT_CLIP, AT_CMER, AT_CMGR, AT_CMS_ERROR, AT_CMTI, AT_CUSD, AT_ECAM, AT_ERROR, at_msg2str(), AT_NO_CARRIER, AT_NO_DIALTONE, AT_OK, AT_PARSE_ERROR, AT_READ_ERROR, at_read_full(), AT_RING, AT_SMS_PROMPT, AT_UNKNOWN, mbl_pvt::blackberry, buf, check_unloading(), mbl_pvt::connected, adapter_pvt::entry, errno, EVENT_FLAG_SYSTEM, msg_queue_entry::expected, handle_response_brsf(), handle_response_busy(), handle_response_ciev(), handle_response_cind(), handle_response_clip(), handle_response_cmgr(), handle_response_cmti(), handle_response_cusd(), handle_response_error(), handle_response_no_carrier(), handle_response_no_dialtone(), handle_response_ok(), handle_response_ring(), handle_sms_prompt(), mbl_pvt::hfp, hfp_parse_ecav(), hfp_send_brsf(), mbl_pvt::id, hfp_pvt::initialized, adapter_pvt::inuse, mbl_pvt::lock, manager_event, mbl_queue_hangup(), msg_queue_flush(), msg_queue_head(), msg_queue_push(), mbl_pvt::needchup, NULL, mbl_pvt::owner, hfp_pvt::owner, msg_queue_entry::response_to, mbl_pvt::rfcomm_socket, rfcomm_wait(), hfp_pvt::rsock, mbl_pvt::sco_socket, and mbl_pvt::timeout.

Referenced by start_monitor().

3871 {
3872  struct mbl_pvt *pvt = (struct mbl_pvt *)data;
3873  struct hfp_pvt *hfp = pvt->hfp;
3874  char buf[350];
3875  int t;
3876  at_message_t at_msg;
3877  struct msg_queue_entry *entry;
3878 
3879  /* Note: At one point the initialization procedure was neatly contained
3880  * in the hfp_init() function, but that initialization method did not
3881  * work with non standard devices. As a result, the initialization
3882  * procedure is not spread throughout the event handling loop.
3883  */
3884 
3885  /* start initialization with the BRSF request */
3886  ast_mutex_lock(&pvt->lock);
3887  pvt->timeout = 10000;
3888  if (hfp_send_brsf(hfp, &hfp_our_brsf) || msg_queue_push(pvt, AT_BRSF, AT_BRSF)) {
3889  ast_debug(1, "[%s] error sending BRSF\n", hfp->owner->id);
3890  goto e_cleanup;
3891  }
3892  ast_mutex_unlock(&pvt->lock);
3893 
3894  while (!check_unloading()) {
3895  ast_mutex_lock(&pvt->lock);
3896  t = pvt->timeout;
3897  ast_mutex_unlock(&pvt->lock);
3898 
3899  if (!rfcomm_wait(pvt->rfcomm_socket, &t)) {
3900  ast_debug(1, "[%s] timeout waiting for rfcomm data, disconnecting\n", pvt->id);
3901  ast_mutex_lock(&pvt->lock);
3902  if (!hfp->initialized) {
3903  if ((entry = msg_queue_head(pvt))) {
3904  switch (entry->response_to) {
3905  case AT_CIND_TEST:
3906  if (pvt->blackberry)
3907  ast_debug(1, "[%s] timeout during CIND test\n", hfp->owner->id);
3908  else
3909  ast_debug(1, "[%s] timeout during CIND test, try setting 'blackberry=yes'\n", hfp->owner->id);
3910  break;
3911  case AT_CMER:
3912  if (pvt->blackberry)
3913  ast_debug(1, "[%s] timeout after sending CMER, try setting 'blackberry=no'\n", hfp->owner->id);
3914  else
3915  ast_debug(1, "[%s] timeout after sending CMER\n", hfp->owner->id);
3916  break;
3917  default:
3918  ast_debug(1, "[%s] timeout while waiting for %s in response to %s\n", pvt->id, at_msg2str(entry->expected), at_msg2str(entry->response_to));
3919  break;
3920  }
3921  }
3922  }
3923  ast_mutex_unlock(&pvt->lock);
3924  goto e_cleanup;
3925  }
3926 
3927  if ((at_msg = at_read_full(hfp->rsock, buf, sizeof(buf))) < 0) {
3928  ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
3929  break;
3930  }
3931 
3932  ast_debug(1, "[%s] read %s\n", pvt->id, buf);
3933 
3934  switch (at_msg) {
3935  case AT_BRSF:
3936  ast_mutex_lock(&pvt->lock);
3937  if (handle_response_brsf(pvt, buf)) {
3938  ast_mutex_unlock(&pvt->lock);
3939  goto e_cleanup;
3940  }
3941  ast_mutex_unlock(&pvt->lock);
3942  break;
3943  case AT_CIND:
3944  ast_mutex_lock(&pvt->lock);
3945  if (handle_response_cind(pvt, buf)) {
3946  ast_mutex_unlock(&pvt->lock);
3947  goto e_cleanup;
3948  }
3949  ast_mutex_unlock(&pvt->lock);
3950  break;
3951  case AT_OK:
3952  ast_mutex_lock(&pvt->lock);
3953  if (handle_response_ok(pvt, buf)) {
3954  ast_mutex_unlock(&pvt->lock);
3955  goto e_cleanup;
3956  }
3957  ast_mutex_unlock(&pvt->lock);
3958  break;
3959  case AT_CMS_ERROR:
3960  case AT_ERROR:
3961  ast_mutex_lock(&pvt->lock);
3962  if (handle_response_error(pvt, buf)) {
3963  ast_mutex_unlock(&pvt->lock);
3964  goto e_cleanup;
3965  }
3966  ast_mutex_unlock(&pvt->lock);
3967  break;
3968  case AT_RING:
3969  ast_mutex_lock(&pvt->lock);
3970  if (handle_response_ring(pvt, buf)) {
3971  ast_mutex_unlock(&pvt->lock);
3972  goto e_cleanup;
3973  }
3974  ast_mutex_unlock(&pvt->lock);
3975  break;
3976  case AT_CIEV:
3977  ast_mutex_lock(&pvt->lock);
3978  if (handle_response_ciev(pvt, buf)) {
3979  ast_mutex_unlock(&pvt->lock);
3980  goto e_cleanup;
3981  }
3982  ast_mutex_unlock(&pvt->lock);
3983  break;
3984  case AT_CLIP:
3985  ast_mutex_lock(&pvt->lock);
3986  if (handle_response_clip(pvt, buf)) {
3987  ast_mutex_unlock(&pvt->lock);
3988  goto e_cleanup;
3989  }
3990  ast_mutex_unlock(&pvt->lock);
3991  break;
3992  case AT_CMTI:
3993  ast_mutex_lock(&pvt->lock);
3994  if (handle_response_cmti(pvt, buf)) {
3995  ast_mutex_unlock(&pvt->lock);
3996  goto e_cleanup;
3997  }
3998  ast_mutex_unlock(&pvt->lock);
3999  break;
4000  case AT_CMGR:
4001  ast_mutex_lock(&pvt->lock);
4002  if (handle_response_cmgr(pvt, buf)) {
4003  ast_mutex_unlock(&pvt->lock);
4004  goto e_cleanup;
4005  }
4006  ast_mutex_unlock(&pvt->lock);
4007  break;
4008  case AT_SMS_PROMPT:
4009  ast_mutex_lock(&pvt->lock);
4010  if (handle_sms_prompt(pvt, buf)) {
4011  ast_mutex_unlock(&pvt->lock);
4012  goto e_cleanup;
4013  }
4014  ast_mutex_unlock(&pvt->lock);
4015  break;
4016  case AT_CUSD:
4017  ast_mutex_lock(&pvt->lock);
4018  if (handle_response_cusd(pvt, buf)) {
4019  ast_mutex_unlock(&pvt->lock);
4020  goto e_cleanup;
4021  }
4022  ast_mutex_unlock(&pvt->lock);
4023  break;
4024  case AT_BUSY:
4025  ast_mutex_lock(&pvt->lock);
4026  if (handle_response_busy(pvt)) {
4027  ast_mutex_unlock(&pvt->lock);
4028  goto e_cleanup;
4029  }
4030  ast_mutex_unlock(&pvt->lock);
4031  break;
4032  case AT_NO_DIALTONE:
4033  ast_mutex_lock(&pvt->lock);
4034  if (handle_response_no_dialtone(pvt, buf)) {
4035  ast_mutex_unlock(&pvt->lock);
4036  goto e_cleanup;
4037  }
4038  ast_mutex_unlock(&pvt->lock);
4039  break;
4040  case AT_NO_CARRIER:
4041  ast_mutex_lock(&pvt->lock);
4042  if (handle_response_no_carrier(pvt, buf)) {
4043  ast_mutex_unlock(&pvt->lock);
4044  goto e_cleanup;
4045  }
4046  ast_mutex_unlock(&pvt->lock);
4047  break;
4048  case AT_ECAM:
4049  ast_mutex_lock(&pvt->lock);
4050  if (hfp_parse_ecav(hfp, buf) == 7) {
4051  if (handle_response_busy(pvt)) {
4052  ast_mutex_unlock(&pvt->lock);
4053  goto e_cleanup;
4054  }
4055  }
4056  ast_mutex_unlock(&pvt->lock);
4057  break;
4058  case AT_UNKNOWN:
4059  ast_debug(1, "[%s] ignoring unknown message: %s\n", pvt->id, buf);
4060  break;
4061  case AT_PARSE_ERROR:
4062  ast_debug(1, "[%s] error parsing message\n", pvt->id);
4063  goto e_cleanup;
4064  case AT_READ_ERROR:
4065  ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
4066  goto e_cleanup;
4067  default:
4068  break;
4069  }
4070  }
4071 
4072 e_cleanup:
4073 
4074  if (!hfp->initialized)
4075  ast_verb(3, "Error initializing Bluetooth device %s.\n", pvt->id);
4076 
4077  ast_mutex_lock(&pvt->lock);
4078  if (pvt->owner) {
4079  ast_debug(1, "[%s] device disconnected, hanging up owner\n", pvt->id);
4080  pvt->needchup = 0;
4081  mbl_queue_hangup(pvt);
4082  }
4083 
4084  close(pvt->rfcomm_socket);
4085  close(pvt->sco_socket);
4086  pvt->sco_socket = -1;
4087 
4088  msg_queue_flush(pvt);
4089 
4090  pvt->connected = 0;
4091  hfp->initialized = 0;
4092 
4093  pvt->adapter->inuse = 0;
4094  ast_mutex_unlock(&pvt->lock);
4095 
4096  ast_verb(3, "Bluetooth Device %s has disconnected.\n", pvt->id);
4097  manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
4098 
4099  return NULL;
4100 }
static int mbl_queue_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1334
static int handle_response_busy(struct mbl_pvt *pvt)
Handle BUSY messages.
Definition: chan_mobile.c:3831
static int handle_response_cind(struct mbl_pvt *pvt, char *buf)
Handle the CIND response.
Definition: chan_mobile.c:3231
static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
Handle AT+CIEV messages.
Definition: chan_mobile.c:3559
static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf)
Handle NO CARRIER messages.
Definition: chan_mobile.c:3861
int sco_socket
Definition: chan_mobile.c:137
static int rfcomm_wait(int rsock, int *ms)
Wait for activity on an rfcomm socket.
Definition: chan_mobile.c:1479
unsigned int connected
Definition: chan_mobile.c:161
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct hfp_hf hfp_our_brsf
Definition: chan_mobile.c:361
static int handle_response_brsf(struct mbl_pvt *pvt, char *buf)
Handle the BRSF response.
Definition: chan_mobile.c:3196
static int check_unloading(void)
Check if the module is unloading.
Definition: chan_mobile.c:4682
int rsock
Definition: chan_mobile.c:352
unsigned int blackberry
Definition: chan_mobile.c:144
static int handle_response_cmti(struct mbl_pvt *pvt, char *buf)
Handle AT+CMTI messages.
Definition: chan_mobile.c:3708
int timeout
Definition: chan_mobile.c:139
#define ast_mutex_lock(a)
Definition: lock.h:187
unsigned int inuse
Definition: chan_mobile.c:104
#define NULL
Definition: resample.c:96
int rfcomm_socket
Definition: chan_mobile.c:132
static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf)
Handle NO DIALTONE messages.
Definition: chan_mobile.c:3846
static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf)
Handle AT+CMGR messages.
Definition: chan_mobile.c:3735
#define ast_verb(level,...)
Definition: logger.h:463
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int handle_response_cusd(struct mbl_pvt *pvt, char *buf)
Handle CUSD messages.
Definition: chan_mobile.c:3811
struct mbl_pvt * owner
Definition: chan_mobile.c:345
static int handle_response_clip(struct mbl_pvt *pvt, char *buf)
Handle AT+CLIP messages.
Definition: chan_mobile.c:3651
static int hfp_send_brsf(struct hfp_pvt *hfp, struct hfp_hf *brsf)
Send a BRSF request.
Definition: chan_mobile.c:2514
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int handle_response_ring(struct mbl_pvt *pvt, char *buf)
Handle RING messages.
Definition: chan_mobile.c:3691
static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
Parse a ECAV event.
Definition: chan_mobile.c:2164
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
static int handle_response_ok(struct mbl_pvt *pvt, char *buf)
Handle OK AT messages.
Definition: chan_mobile.c:3273
int initialized
Definition: chan_mobile.c:346
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
at_message_t expected
Definition: chan_mobile.c:461
struct ast_channel * owner
Definition: chan_mobile.c:119
char id[31]
Definition: chan_mobile.c:125
at_message_t response_to
Definition: chan_mobile.c:462
unsigned int needchup
Definition: chan_mobile.c:158
int errno
ast_mutex_t lock
Definition: chan_mobile.c:121
Definition: chan_mobile.c:460
static at_message_t at_read_full(int rsock, char *buf, size_t count)
Read an AT message and clasify it.
Definition: chan_mobile.c:2017
at_message_t
Definition: chan_mobile.c:419
struct adapter_pvt * adapter
Definition: chan_mobile.c:128
static void msg_queue_flush(struct mbl_pvt *pvt)
Remove all itmes from the queue and free them.
Definition: chan_mobile.c:3046
static int handle_response_error(struct mbl_pvt *pvt, char *buf)
Handle ERROR AT messages.
Definition: chan_mobile.c:3442
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
This struct holds state information about the current hfp connection.
Definition: chan_mobile.c:344
static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf)
Send an SMS message from the queue.
Definition: chan_mobile.c:3780
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
#define ast_mutex_unlock(a)
Definition: lock.h:188
struct msg_queue_entry::@6 entry

◆ do_sco_listen()

static void * do_sco_listen ( void *  data)
static

Service new and existing SCO connections. This thread accepts new sco connections and handles audio data. There is one do_sco_listen thread for each adapter.

Definition at line 4326 of file chan_mobile.c.

References adapter_pvt::accept_io, ast_io_wait(), ast_log, check_unloading(), adapter_pvt::id, adapter_pvt::io, LOG_ERROR, and NULL.

Referenced by mbl_load_adapter().

4327 {
4328  struct adapter_pvt *adapter = (struct adapter_pvt *) data;
4329 
4330  while (!check_unloading()) {
4331  /* check for new sco connections */
4332  if (ast_io_wait(adapter->accept_io, 0) == -1) {
4333  /* handle errors */
4334  ast_log(LOG_ERROR, "ast_io_wait() failed for adapter %s\n", adapter->id);
4335  break;
4336  }
4337 
4338  /* handle audio data */
4339  if (ast_io_wait(adapter->io, 1) == -1) {
4340  ast_log(LOG_ERROR, "ast_io_wait() failed for audio on adapter %s\n", adapter->id);
4341  break;
4342  }
4343  }
4344 
4345  return NULL;
4346 }
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:278
char id[31]
Definition: chan_mobile.c:102
struct io_context * accept_io
Definition: chan_mobile.c:107
static int check_unloading(void)
Check if the module is unloading.
Definition: chan_mobile.c:4682
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
struct io_context * io
Definition: chan_mobile.c:106
#define LOG_ERROR
Definition: logger.h:285

◆ handle_cli_mobile_cusd()

static char * handle_cli_mobile_cusd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 659 of file chan_mobile.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AT_CUSD, AT_OK, buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mbl_pvt::connected, ast_cli_args::fd, mbl_pvt::hfp, hfp_send_cusd(), mbl_pvt::id, mbl_pvt::lock, msg_queue_push(), NULL, and ast_cli_entry::usage.

660 {
661  char buf[128];
662  struct mbl_pvt *pvt = NULL;
663 
664  switch (cmd) {
665  case CLI_INIT:
666  e->command = "mobile cusd";
667  e->usage =
668  "Usage: mobile cusd <device ID> <command>\n"
669  " Send cusd <command> to the rfcomm port on the device\n"
670  " with the specified <device ID>.\n";
671  return NULL;
672  case CLI_GENERATE:
673  return NULL;
674  }
675 
676  if (a->argc != 4)
677  return CLI_SHOWUSAGE;
678 
681  if (!strcmp(pvt->id, a->argv[2]))
682  break;
683  }
685 
686  if (!pvt) {
687  ast_cli(a->fd, "Device %s not found.\n", a->argv[2]);
688  goto e_return;
689  }
690 
691  ast_mutex_lock(&pvt->lock);
692  if (!pvt->connected) {
693  ast_cli(a->fd, "Device %s not connected.\n", a->argv[2]);
694  goto e_unlock_pvt;
695  }
696 
697  snprintf(buf, sizeof(buf), "%s", a->argv[3]);
698  if (hfp_send_cusd(pvt->hfp, buf) || msg_queue_push(pvt, AT_OK, AT_CUSD)) {
699  ast_cli(a->fd, "[%s] error sending CUSD\n", pvt->id);
700  goto e_unlock_pvt;
701  }
702 
703 e_unlock_pvt:
704  ast_mutex_unlock(&pvt->lock);
705 e_return:
706  return CLI_SUCCESS;
707 }
unsigned int connected
Definition: chan_mobile.c:161
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char id[31]
Definition: chan_mobile.c:125
ast_mutex_t lock
Definition: chan_mobile.c:121
static int hfp_send_cusd(struct hfp_pvt *hfp, const char *code)
Send CUSD.
Definition: chan_mobile.c:2712
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: search.h:40
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ handle_cli_mobile_rfcomm()

static char * handle_cli_mobile_rfcomm ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 611 of file chan_mobile.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AT_OK, AT_UNKNOWN, buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mbl_pvt::connected, ast_cli_args::fd, mbl_pvt::id, mbl_pvt::lock, msg_queue_push(), NULL, mbl_pvt::rfcomm_socket, rfcomm_write(), and ast_cli_entry::usage.

612 {
613  char buf[128];
614  struct mbl_pvt *pvt = NULL;
615 
616  switch (cmd) {
617  case CLI_INIT:
618  e->command = "mobile rfcomm";
619  e->usage =
620  "Usage: mobile rfcomm <device ID> <command>\n"
621  " Send <command> to the rfcomm port on the device\n"
622  " with the specified <device ID>.\n";
623  return NULL;
624  case CLI_GENERATE:
625  return NULL;
626  }
627 
628  if (a->argc != 4)
629  return CLI_SHOWUSAGE;
630 
633  if (!strcmp(pvt->id, a->argv[2]))
634  break;
635  }
637 
638  if (!pvt) {
639  ast_cli(a->fd, "Device %s not found.\n", a->argv[2]);
640  goto e_return;
641  }
642 
643  ast_mutex_lock(&pvt->lock);
644  if (!pvt->connected) {
645  ast_cli(a->fd, "Device %s not connected.\n", a->argv[2]);
646  goto e_unlock_pvt;
647  }
648 
649  snprintf(buf, sizeof(buf), "%s\r", a->argv[3]);
650  rfcomm_write(pvt->rfcomm_socket, buf);
652 
653 e_unlock_pvt:
654  ast_mutex_unlock(&pvt->lock);
655 e_return:
656  return CLI_SUCCESS;
657 }
unsigned int connected
Definition: chan_mobile.c:161
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
int rfcomm_socket
Definition: chan_mobile.c:132
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char id[31]
Definition: chan_mobile.c:125
ast_mutex_t lock
Definition: chan_mobile.c:121
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: search.h:40
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ handle_cli_mobile_search()

static char * handle_cli_mobile_search ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 541 of file chan_mobile.c.

References adapter_pvt::addr, ast_cli_args::argc, ast_alloca, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, adapter_pvt::dev_id, ast_cli_args::fd, FORMAT1, FORMAT2, adapter_pvt::hci_socket, adapter_pvt::inuse, len(), name, NULL, sdp_search(), and ast_cli_entry::usage.

542 {
543  struct adapter_pvt *adapter;
544  inquiry_info *ii = NULL;
545  int max_rsp, num_rsp;
546  int len, flags;
547  int i, phport, hsport;
548  char addr[19] = {0};
549  char name[31] = {0};
550 
551 #define FORMAT1 "%-17.17s %-30.30s %-6.6s %-7.7s %-4.4s\n"
552 #define FORMAT2 "%-17.17s %-30.30s %-6.6s %-7.7s %d\n"
553 
554  switch (cmd) {
555  case CLI_INIT:
556  e->command = "mobile search";
557  e->usage =
558  "Usage: mobile search\n"
559  " Searches for Bluetooth Cell / Mobile devices in range.\n";
560  return NULL;
561  case CLI_GENERATE:
562  return NULL;
563  }
564 
565  if (a->argc != 2)
566  return CLI_SHOWUSAGE;
567 
568  /* find a free adapter */
570  AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
571  if (!adapter->inuse)
572  break;
573  }
575 
576  if (!adapter) {
577  ast_cli(a->fd, "All Bluetooth adapters are in use at this time.\n");
578  return CLI_SUCCESS;
579  }
580 
581  len = 8;
582  max_rsp = 255;
583  flags = IREQ_CACHE_FLUSH;
584 
585  ii = ast_alloca(max_rsp * sizeof(inquiry_info));
586  num_rsp = hci_inquiry(adapter->dev_id, len, max_rsp, NULL, &ii, flags);
587  if (num_rsp > 0) {
588  ast_cli(a->fd, FORMAT1, "Address", "Name", "Usable", "Type", "Port");
589  for (i = 0; i < num_rsp; i++) {
590  ba2str(&(ii + i)->bdaddr, addr);
591  name[0] = 0x00;
592  if (hci_read_remote_name(adapter->hci_socket, &(ii + i)->bdaddr, sizeof(name) - 1, name, 0) < 0)
593  strcpy(name, "[unknown]");
594  phport = sdp_search(addr, HANDSFREE_AGW_PROFILE_ID);
595  if (!phport)
596  hsport = sdp_search(addr, HEADSET_PROFILE_ID);
597  else
598  hsport = 0;
599  ast_cli(a->fd, FORMAT2, addr, name, (phport > 0 || hsport > 0) ? "Yes" : "No",
600  (phport > 0) ? "Phone" : "Headset", (phport > 0) ? phport : hsport);
601  }
602  } else
603  ast_cli(a->fd, "No Bluetooth Cell / Mobile devices found.\n");
604 
605 #undef FORMAT1
606 #undef FORMAT2
607 
608  return CLI_SUCCESS;
609 }
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define FORMAT2
Definition: cli.h:152
unsigned int inuse
Definition: chan_mobile.c:104
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define FORMAT1
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static const char name[]
Definition: cdr_mysql.c:74
char * command
Definition: cli.h:186
bdaddr_t addr
Definition: chan_mobile.c:103
static int sdp_search(char *addr, int profile)
Definition: chan_mobile.c:3071
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: search.h:40

◆ handle_cli_mobile_show_devices()

static char * handle_cli_mobile_show_devices ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 495 of file chan_mobile.c.

References mbl_pvt::adapter, mbl_pvt::addr, ast_cli_args::argc, ast_cli(), ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mbl_pvt::connected, ast_cli_args::fd, FORMAT1, mbl_pvt::group, mbl_pvt::has_sms, adapter_pvt::id, mbl_pvt::id, mbl_pvt::incoming_sms, mbl_pvt::lock, mbl_has_service(), NULL, mbl_pvt::outgoing_sms, mbl_pvt::owner, and ast_cli_entry::usage.

496 {
497  struct mbl_pvt *pvt;
498  char bdaddr[18];
499  char group[6];
500 
501 #define FORMAT1 "%-15.15s %-17.17s %-5.5s %-15.15s %-9.9s %-10.10s %-3.3s\n"
502 
503  switch (cmd) {
504  case CLI_INIT:
505  e->command = "mobile show devices";
506  e->usage =
507  "Usage: mobile show devices\n"
508  " Shows the state of Bluetooth Cell / Mobile devices.\n";
509  return NULL;
510  case CLI_GENERATE:
511  return NULL;
512  }
513 
514  if (a->argc != 3)
515  return CLI_SHOWUSAGE;
516 
517  ast_cli(a->fd, FORMAT1, "ID", "Address", "Group", "Adapter", "Connected", "State", "SMS");
520  ast_mutex_lock(&pvt->lock);
521  ba2str(&pvt->addr, bdaddr);
522  snprintf(group, sizeof(group), "%d", pvt->group);
523  ast_cli(a->fd, FORMAT1,
524  pvt->id,
525  bdaddr,
526  group,
527  pvt->adapter->id,
528  pvt->connected ? "Yes" : "No",
529  (!pvt->connected) ? "None" : (pvt->owner) ? "Busy" : (pvt->outgoing_sms || pvt->incoming_sms) ? "SMS" : (mbl_has_service(pvt)) ? "Free" : "No Service",
530  (pvt->has_sms) ? "Yes" : "No"
531  );
532  ast_mutex_unlock(&pvt->lock);
533  }
535 
536 #undef FORMAT1
537 
538  return CLI_SUCCESS;
539 }
char id[31]
Definition: chan_mobile.c:102
unsigned int connected
Definition: chan_mobile.c:161
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define FORMAT1
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
bdaddr_t addr
Definition: chan_mobile.c:127
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
unsigned int has_sms
Definition: chan_mobile.c:141
#define CLI_SHOWUSAGE
Definition: cli.h:45
struct ast_channel * owner
Definition: chan_mobile.c:119
char id[31]
Definition: chan_mobile.c:125
ast_mutex_t lock
Definition: chan_mobile.c:121
char * command
Definition: cli.h:186
unsigned int outgoing_sms
Definition: chan_mobile.c:155
const char * usage
Definition: cli.h:177
unsigned int incoming_sms
Definition: chan_mobile.c:156
#define CLI_SUCCESS
Definition: cli.h:44
struct adapter_pvt * adapter
Definition: chan_mobile.c:128
Definition: search.h:40
int group
Definition: chan_mobile.c:126
#define ast_mutex_unlock(a)
Definition: lock.h:188
static int mbl_has_service(struct mbl_pvt *pvt)
Check if a mobile device has service.
Definition: chan_mobile.c:1369

◆ handle_response_brsf()

static int handle_response_brsf ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle the BRSF response.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3196 of file chan_mobile.c.

References ast_debug, AT_BRSF, at_msg2str(), AT_OK, adapter_pvt::entry, msg_queue_entry::expected, mbl_pvt::hfp, hfp_parse_brsf(), mbl_pvt::id, msg_queue_free_and_pop(), msg_queue_head(), and msg_queue_push().

Referenced by do_monitor_phone().

3197 {
3198  struct msg_queue_entry *entry;
3199  if ((entry = msg_queue_head(pvt)) && entry->expected == AT_BRSF) {
3200  if (hfp_parse_brsf(pvt->hfp, buf)) {
3201  ast_debug(1, "[%s] error parsing BRSF\n", pvt->id);
3202  goto e_return;
3203  }
3204 
3205  if (msg_queue_push(pvt, AT_OK, AT_BRSF)) {
3206  ast_debug(1, "[%s] error handling BRSF\n", pvt->id);
3207  goto e_return;
3208  }
3209 
3211  } else if (entry) {
3212  ast_debug(1, "[%s] received unexpected AT message 'BRSF' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3213  } else {
3214  ast_debug(1, "[%s] received unexpected AT message 'BRSF'\n", pvt->id);
3215  }
3216 
3217  return 0;
3218 
3219 e_return:
3221  return -1;
3222 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int hfp_parse_brsf(struct hfp_pvt *hfp, const char *buf)
Parse BRSF data.
Definition: chan_mobile.c:2724
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
at_message_t expected
Definition: chan_mobile.c:461
char id[31]
Definition: chan_mobile.c:125
Definition: chan_mobile.c:460
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
struct msg_queue_entry::@6 entry

◆ handle_response_busy()

static int handle_response_busy ( struct mbl_pvt pvt)
static

Handle BUSY messages.

Parameters
pvta mbl_pvt structure
Return values
0success
-1error

Definition at line 3831 of file chan_mobile.c.

References AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, mbl_pvt::hangupcause, mbl_queue_control(), and mbl_pvt::needchup.

Referenced by do_monitor_phone(), and handle_response_ciev().

3832 {
3834  pvt->needchup = 1;
3836  return 0;
3837 }
int hangupcause
Definition: chan_mobile.c:150
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
unsigned int needchup
Definition: chan_mobile.c:158
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106

◆ handle_response_ciev()

static int handle_response_ciev ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle AT+CIEV messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3559 of file chan_mobile.c.

References mbl_pvt::answered, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, ast_debug, ast_log, ast_setstate(), AST_STATE_UP, ast_verb, hfp_cind::call, hfp_pvt::cind_map, hfp_pvt::cind_state, handle_response_busy(), mbl_pvt::hfp, HFP_CIND_CALL, HFP_CIND_CALL_ACTIVE, HFP_CIND_CALL_NONE, HFP_CIND_CALLSETUP, HFP_CIND_CALLSETUP_ALERTING, HFP_CIND_CALLSETUP_INCOMING, HFP_CIND_CALLSETUP_NONE, HFP_CIND_CALLSETUP_OUTGOING, HFP_CIND_NONE, hfp_parse_ciev(), mbl_pvt::id, mbl_pvt::incoming, LOG_ERROR, mbl_queue_control(), mbl_queue_hangup(), mbl_pvt::needcallerid, mbl_pvt::needchup, mbl_pvt::outgoing, mbl_pvt::owner, and hfp_pvt::sent_alerting.

Referenced by do_monitor_phone().

3560 {
3561  int i;
3562  switch (hfp_parse_ciev(pvt->hfp, buf, &i)) {
3563  case HFP_CIND_CALL:
3564  switch (i) {
3565  case HFP_CIND_CALL_NONE:
3566  ast_debug(1, "[%s] line disconnected\n", pvt->id);
3567  if (pvt->owner) {
3568  ast_debug(1, "[%s] hanging up owner\n", pvt->id);
3569  if (mbl_queue_hangup(pvt)) {
3570  ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
3571  return -1;
3572  }
3573  }
3574  pvt->needchup = 0;
3575  pvt->needcallerid = 0;
3576  pvt->incoming = 0;
3577  pvt->outgoing = 0;
3578  break;
3579  case HFP_CIND_CALL_ACTIVE:
3580  if (pvt->outgoing) {
3581  ast_debug(1, "[%s] remote end answered\n", pvt->id);
3583  } else if (pvt->incoming && pvt->answered) {
3585  } else if (pvt->incoming) {
3586  /* user answered from handset, disconnecting */
3587  ast_verb(3, "[%s] user answered bluetooth device from handset, disconnecting\n", pvt->id);
3588  mbl_queue_hangup(pvt);
3589  return -1;
3590  }
3591  break;
3592  }
3593  break;
3594 
3595  case HFP_CIND_CALLSETUP:
3596  switch (i) {
3598  if (pvt->hfp->cind_state[pvt->hfp->cind_map.call] != HFP_CIND_CALL_ACTIVE) {
3599  if (pvt->owner) {
3600  if (pvt->hfp->sent_alerting == 1) {
3601  handle_response_busy(pvt);
3602  }
3603  if (mbl_queue_hangup(pvt)) {
3604  ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
3605  return -1;
3606  }
3607  }
3608  pvt->needchup = 0;
3609  pvt->needcallerid = 0;
3610  pvt->incoming = 0;
3611  pvt->outgoing = 0;
3612  }
3613  break;
3615  ast_debug(1, "[%s] incoming call, waiting for caller id\n", pvt->id);
3616  pvt->needcallerid = 1;
3617  pvt->incoming = 1;
3618  break;
3620  if (pvt->outgoing) {
3621  pvt->hfp->sent_alerting = 0;
3622  ast_debug(1, "[%s] outgoing call\n", pvt->id);
3623  } else {
3624  ast_verb(3, "[%s] user dialed from handset, disconnecting\n", pvt->id);
3625  return -1;
3626  }
3627  break;
3629  if (pvt->outgoing) {
3630  ast_debug(1, "[%s] remote alerting\n", pvt->id);
3632  pvt->hfp->sent_alerting = 1;
3633  }
3634  break;
3635  }
3636  break;
3637  case HFP_CIND_NONE:
3638  ast_debug(1, "[%s] error parsing CIND: %s\n", pvt->id, buf);
3639  break;
3640  }
3641  return 0;
3642 }
static int mbl_queue_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1334
static int handle_response_busy(struct mbl_pvt *pvt)
Handle BUSY messages.
Definition: chan_mobile.c:3831
#define HFP_CIND_CALL
Definition: chan_mobile.c:278
#define HFP_CIND_CALL_ACTIVE
Definition: chan_mobile.c:287
#define HFP_CIND_NONE
Definition: chan_mobile.c:276
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define HFP_CIND_CALLSETUP
Definition: chan_mobile.c:279
unsigned int answered
Definition: chan_mobile.c:160
#define HFP_CIND_CALL_NONE
Definition: chan_mobile.c:286
unsigned int incoming
Definition: chan_mobile.c:154
#define HFP_CIND_CALLSETUP_ALERTING
Definition: chan_mobile.c:293
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
int sent_alerting
Definition: chan_mobile.c:354
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
#define LOG_ERROR
Definition: logger.h:285
int cind_state[16]
Definition: chan_mobile.c:350
struct hfp_cind cind_map
Definition: chan_mobile.c:351
struct ast_channel * owner
Definition: chan_mobile.c:119
char id[31]
Definition: chan_mobile.c:125
unsigned int needchup
Definition: chan_mobile.c:158
static int hfp_parse_ciev(struct hfp_pvt *hfp, char *buf, int *value)
Parse a CIEV event.
Definition: chan_mobile.c:2195
#define HFP_CIND_CALLSETUP_INCOMING
Definition: chan_mobile.c:291
unsigned int outgoing
Definition: chan_mobile.c:153
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
unsigned int needcallerid
Definition: chan_mobile.c:157
#define HFP_CIND_CALLSETUP_NONE
Definition: chan_mobile.c:290
#define HFP_CIND_CALLSETUP_OUTGOING
Definition: chan_mobile.c:292

◆ handle_response_cind()

static int handle_response_cind ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle the CIND response.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3231 of file chan_mobile.c.

References ast_debug, AT_CIND, AT_CIND_TEST, at_msg2str(), AT_OK, adapter_pvt::entry, msg_queue_entry::expected, mbl_pvt::hfp, hfp_parse_cind(), hfp_parse_cind_test(), mbl_pvt::id, msg_queue_free_and_pop(), msg_queue_head(), msg_queue_push(), and msg_queue_entry::response_to.

Referenced by do_monitor_phone().

3232 {
3233  struct msg_queue_entry *entry;
3234  if ((entry = msg_queue_head(pvt)) && entry->expected == AT_CIND) {
3235  switch (entry->response_to) {
3236  case AT_CIND_TEST:
3238  ast_debug(1, "[%s] error performing CIND test\n", pvt->id);
3239  goto e_return;
3240  }
3241  break;
3242  case AT_CIND:
3243  if (hfp_parse_cind(pvt->hfp, buf) || msg_queue_push(pvt, AT_OK, AT_CIND)) {
3244  ast_debug(1, "[%s] error getting CIND state\n", pvt->id);
3245  goto e_return;
3246  }
3247  break;
3248  default:
3249  ast_debug(1, "[%s] error getting CIND state\n", pvt->id);
3250  goto e_return;
3251  }
3253  } else if (entry) {
3254  ast_debug(1, "[%s] received unexpected AT message 'CIND' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3255  } else {
3256  ast_debug(1, "[%s] received unexpected AT message 'CIND'\n", pvt->id);
3257  }
3258 
3259  return 0;
3260 
3261 e_return:
3263  return -1;
3264 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int hfp_parse_cind_test(struct hfp_pvt *hfp, char *buf)
Parse the result of the AT+CIND=? command.
Definition: chan_mobile.c:2818
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
at_message_t expected
Definition: chan_mobile.c:461
char id[31]
Definition: chan_mobile.c:125
at_message_t response_to
Definition: chan_mobile.c:462
Definition: chan_mobile.c:460
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
static int hfp_parse_cind(struct hfp_pvt *hfp, char *buf)
Read the result of the AT+CIND? command.
Definition: chan_mobile.c:2768
struct msg_queue_entry::@6 entry

◆ handle_response_clip()

static int handle_response_clip ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle AT+CLIP messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3651 of file chan_mobile.c.

References ast_log, ast_pbx_start(), AST_STATE_RING, AT_CHUP, AT_CLIP, AT_OK, msg_queue_entry::expected, mbl_pvt::hfp, hfp_parse_clip(), hfp_send_chup(), mbl_pvt::id, LOG_ERROR, mbl_ast_hangup(), mbl_new(), msg_queue_free_and_pop(), msg_queue_head(), msg_queue_push(), mbl_pvt::needcallerid, mbl_pvt::needchup, and NULL.

Referenced by do_monitor_phone().

3652 {
3653  struct msg_queue_entry *msg;
3654  struct ast_channel *chan;
3655  struct cidinfo cidinfo;
3656 
3657  if ((msg = msg_queue_head(pvt)) && msg->expected == AT_CLIP) {
3659 
3660  pvt->needcallerid = 0;
3661  cidinfo = hfp_parse_clip(pvt->hfp, buf);
3662 
3663  if (!(chan = mbl_new(AST_STATE_RING, pvt, &cidinfo, NULL, NULL))) {
3664  ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);
3665  hfp_send_chup(pvt->hfp);
3666  msg_queue_push(pvt, AT_OK, AT_CHUP);
3667  return -1;
3668  }
3669 
3670  /* from this point on, we need to send a chup in the event of a
3671  * hangup */
3672  pvt->needchup = 1;
3673 
3674  if (ast_pbx_start(chan)) {
3675  ast_log(LOG_ERROR, "[%s] unable to start pbx on incoming call\n", pvt->id);
3676  mbl_ast_hangup(pvt);
3677  return -1;
3678  }
3679  }
3680 
3681  return 0;
3682 }
Main Channel structure associated with a channel.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
#define NULL
Definition: resample.c:96
static int mbl_ast_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1354
#define ast_log
Definition: astobj2.c:42
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
#define LOG_ERROR
Definition: logger.h:285
at_message_t expected
Definition: chan_mobile.c:461
char id[31]
Definition: chan_mobile.c:125
unsigned int needchup
Definition: chan_mobile.c:158
static int hfp_send_chup(struct hfp_pvt *hfp)
Send AT+CHUP.
Definition: chan_mobile.c:2681
Definition: chan_mobile.c:460
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
unsigned int needcallerid
Definition: chan_mobile.c:157
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
static struct cidinfo hfp_parse_clip(struct hfp_pvt *hfp, char *buf)
Parse a CLIP event.
Definition: chan_mobile.c:2224
static struct ast_channel * mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_mobile.c:847

◆ handle_response_cmgr()

static int handle_response_cmgr ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle AT+CMGR messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3735 of file chan_mobile.c.

References ast_channel_exten_set(), ast_debug, ast_log, ast_pbx_start(), AST_STATE_DOWN, AT_CMGR, msg_queue_entry::expected, mbl_pvt::hfp, hfp_parse_cmgr(), mbl_pvt::id, mbl_pvt::incoming_sms, LOG_ERROR, mbl_ast_hangup(), mbl_new(), msg_queue_free_and_pop(), msg_queue_head(), NULL, pbx_builtin_setvar_helper(), and text.

Referenced by do_monitor_phone().

3736 {
3737  char *from_number = NULL, *text = NULL;
3738  struct ast_channel *chan;
3739  struct msg_queue_entry *msg;
3740 
3741  if ((msg = msg_queue_head(pvt)) && msg->expected == AT_CMGR) {
3743 
3744  if (hfp_parse_cmgr(pvt->hfp, buf, &from_number, &text)) {
3745  ast_debug(1, "[%s] error parsing sms message, disconnecting\n", pvt->id);
3746  return -1;
3747  }
3748 
3749  ast_debug(1, "[%s] successfully read sms message\n", pvt->id);
3750  pvt->incoming_sms = 0;
3751 
3752  /* XXX this channel probably does not need to be associated with this pvt */
3753  if (!(chan = mbl_new(AST_STATE_DOWN, pvt, NULL, NULL, NULL))) {
3754  ast_debug(1, "[%s] error creating sms message channel, disconnecting\n", pvt->id);
3755  return -1;
3756  }
3757 
3758  ast_channel_exten_set(chan, "sms");
3759  pbx_builtin_setvar_helper(chan, "SMSSRC", from_number);
3760  pbx_builtin_setvar_helper(chan, "SMSTXT", text);
3761 
3762  if (ast_pbx_start(chan)) {
3763  ast_log(LOG_ERROR, "[%s] unable to start pbx on incoming sms\n", pvt->id);
3764  mbl_ast_hangup(pvt);
3765  }
3766  } else {
3767  ast_debug(1, "[%s] got unexpected +CMGR message, ignoring\n", pvt->id);
3768  }
3769 
3770  return 0;
3771 }
Main Channel structure associated with a channel.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4712
char * text
Definition: app_queue.c:1508
#define NULL
Definition: resample.c:96
static int mbl_ast_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1354
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
#define LOG_ERROR
Definition: logger.h:285
at_message_t expected
Definition: chan_mobile.c:461
char id[31]
Definition: chan_mobile.c:125
Definition: chan_mobile.c:460
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
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...
unsigned int incoming_sms
Definition: chan_mobile.c:156
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
static int hfp_parse_cmgr(struct hfp_pvt *hfp, char *buf, char **from_number, char **text)
Parse a CMGR message.
Definition: chan_mobile.c:2352
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
static struct ast_channel * mbl_new(int state, struct mbl_pvt *pvt, struct cidinfo *cidinfo, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_mobile.c:847

◆ handle_response_cmti()

static int handle_response_cmti ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle AT+CMTI messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3708 of file chan_mobile.c.

References ast_debug, AT_CMGR, mbl_pvt::hfp, hfp_parse_cmti(), hfp_send_cmgr(), mbl_pvt::id, mbl_pvt::incoming_sms, and msg_queue_push().

Referenced by do_monitor_phone().

3709 {
3710  int index = hfp_parse_cmti(pvt->hfp, buf);
3711  if (index > 0) {
3712  ast_debug(1, "[%s] incoming sms message\n", pvt->id);
3713 
3714  if (hfp_send_cmgr(pvt->hfp, index)
3715  || msg_queue_push(pvt, AT_CMGR, AT_CMGR)) {
3716  ast_debug(1, "[%s] error sending CMGR to retrieve SMS message\n", pvt->id);
3717  return -1;
3718  }
3719 
3720  pvt->incoming_sms = 1;
3721  return 0;
3722  } else {
3723  ast_debug(1, "[%s] error parsing incoming sms message alert, disconnecting\n", pvt->id);
3724  return -1;
3725  }
3726 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int hfp_parse_cmti(struct hfp_pvt *hfp, char *buf)
Parse a CMTI notification.
Definition: chan_mobile.c:2326
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
char id[31]
Definition: chan_mobile.c:125
static int hfp_send_cmgr(struct hfp_pvt *hfp, int index)
Read an SMS message.
Definition: chan_mobile.c:2646
unsigned int incoming_sms
Definition: chan_mobile.c:156

◆ handle_response_cusd()

static int handle_response_cusd ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle CUSD messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3811 of file chan_mobile.c.

References ast_verb, mbl_pvt::hfp, hfp_parse_cusd(), and mbl_pvt::id.

Referenced by do_monitor_phone().

3812 {
3813  char *cusd;
3814 
3815  if (!(cusd = hfp_parse_cusd(pvt->hfp, buf))) {
3816  ast_verb(0, "[%s] error parsing CUSD: %s\n", pvt->id, buf);
3817  return 0;
3818  }
3819 
3820  ast_verb(0, "[%s] CUSD response: %s\n", pvt->id, cusd);
3821 
3822  return 0;
3823 }
static char * hfp_parse_cusd(struct hfp_pvt *hfp, char *buf)
Parse a CUSD answer.
Definition: chan_mobile.c:2416
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_verb(level,...)
Definition: logger.h:463
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
char id[31]
Definition: chan_mobile.c:125

◆ handle_response_error()

static int handle_response_error ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle ERROR AT messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3442 of file chan_mobile.c.

References AST_CONTROL_CONGESTION, ast_debug, ast_verb, AT_A, AT_BRSF, AT_CHUP, AT_CIND, AT_CIND_TEST, AT_CLIP, AT_CMER, AT_CMGF, AT_CMGR, AT_CMGS, AT_CMS_ERROR, AT_CNMI, AT_CUSD, AT_D, AT_ECAM, AT_ERROR, at_msg2str(), AT_OK, AT_SMS_PROMPT, AT_UNKNOWN, AT_VGS, AT_VTS, adapter_pvt::entry, msg_queue_entry::expected, mbl_pvt::has_sms, mbl_pvt::hfp, hfp_send_cmgf(), hfp_send_vgs(), mbl_pvt::id, mbl_pvt::incoming_sms, hfp_pvt::initialized, mbl_queue_control(), mbl_queue_hangup(), msg_queue_free_and_pop(), msg_queue_head(), msg_queue_push(), mbl_pvt::needchup, mbl_pvt::outgoing_sms, msg_queue_entry::response_to, and mbl_pvt::timeout.

Referenced by do_monitor_phone().

3443 {
3444  struct msg_queue_entry *entry;
3445  if ((entry = msg_queue_head(pvt))
3446  && (entry->expected == AT_OK
3447  || entry->expected == AT_ERROR
3448  || entry->expected == AT_CMS_ERROR
3449  || entry->expected == AT_CMGR
3450  || entry->expected == AT_SMS_PROMPT)) {
3451  switch (entry->response_to) {
3452 
3453  /* initialization stuff */
3454  case AT_BRSF:
3455  ast_debug(1, "[%s] error reading BSRF\n", pvt->id);
3456  goto e_return;
3457  case AT_CIND_TEST:
3458  ast_debug(1, "[%s] error during CIND test\n", pvt->id);
3459  goto e_return;
3460  case AT_CIND:
3461  ast_debug(1, "[%s] error requesting CIND state\n", pvt->id);
3462  goto e_return;
3463  case AT_CMER:
3464  ast_debug(1, "[%s] error during CMER request\n", pvt->id);
3465  goto e_return;
3466  case AT_CLIP:
3467  ast_debug(1, "[%s] error enabling calling line indication\n", pvt->id);
3468  goto e_return;
3469  case AT_VGS:
3470  ast_debug(1, "[%s] volume level synchronization failed\n", pvt->id);
3471 
3472  /* this is not a fatal error, let's continue with initialization */
3473 
3474  /* set the SMS operating mode to text mode */
3475  if (hfp_send_cmgf(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMGF)) {
3476  ast_debug(1, "[%s] error setting CMGF\n", pvt->id);
3477  goto e_return;
3478  }
3479  break;
3480  case AT_CMGF:
3481  pvt->has_sms = 0;
3482  ast_debug(1, "[%s] error setting CMGF\n", pvt->id);
3483  ast_debug(1, "[%s] no SMS support\n", pvt->id);
3484  break;
3485  case AT_CNMI:
3486  pvt->has_sms = 0;
3487  ast_debug(1, "[%s] error setting CNMI\n", pvt->id);
3488  ast_debug(1, "[%s] no SMS support\n", pvt->id);
3489  break;
3490  case AT_ECAM:
3491  ast_debug(1, "[%s] Mobile does not support Sony Ericsson extensions\n", pvt->id);
3492 
3493  /* this is not a fatal error, let's continue with the initialization */
3494 
3495  if (hfp_send_vgs(pvt->hfp, 15) || msg_queue_push(pvt, AT_OK, AT_VGS)) {
3496  ast_debug(1, "[%s] error synchronizing gain settings\n", pvt->id);
3497  goto e_return;
3498  }
3499 
3500  pvt->timeout = -1;
3501  pvt->hfp->initialized = 1;
3502  ast_verb(3, "Bluetooth Device %s initialized and ready.\n", pvt->id);
3503 
3504  break;
3505  /* end initialization stuff */
3506 
3507  case AT_A:
3508  ast_debug(1, "[%s] answer failed\n", pvt->id);
3509  mbl_queue_hangup(pvt);
3510  break;
3511  case AT_D:
3512  ast_debug(1, "[%s] dial failed\n", pvt->id);
3513  pvt->needchup = 0;
3515  break;
3516  case AT_CHUP:
3517  ast_debug(1, "[%s] error sending hangup, disconnecting\n", pvt->id);
3518  goto e_return;
3519  case AT_CMGR:
3520  ast_debug(1, "[%s] error reading sms message\n", pvt->id);
3521  pvt->incoming_sms = 0;
3522  break;
3523  case AT_CMGS:
3524  ast_debug(1, "[%s] error sending sms message\n", pvt->id);
3525  pvt->outgoing_sms = 0;
3526  break;
3527  case AT_VTS:
3528  ast_debug(1, "[%s] error sending digit\n", pvt->id);
3529  break;
3530  case AT_CUSD:
3531  ast_verb(0, "[%s] error sending CUSD command\n", pvt->id);
3532  break;
3533  case AT_UNKNOWN:
3534  default:
3535  ast_debug(1, "[%s] received ERROR for unhandled request: %s\n", pvt->id, at_msg2str(entry->response_to));
3536  break;
3537  }
3539  } else if (entry) {
3540  ast_debug(1, "[%s] received AT message 'ERROR' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3541  } else {
3542  ast_debug(1, "[%s] received unexpected AT message 'ERROR'\n", pvt->id);
3543  }
3544 
3545  return 0;
3546 
3547 e_return:
3549  return -1;
3550 }
static int mbl_queue_hangup(struct mbl_pvt *pvt)
Definition: chan_mobile.c:1334
int timeout
Definition: chan_mobile.c:139
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int hfp_send_vgs(struct hfp_pvt *hfp, int value)
Send the current speaker gain level.
Definition: chan_mobile.c:2556
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
unsigned int has_sms
Definition: chan_mobile.c:141
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
int initialized
Definition: chan_mobile.c:346
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
at_message_t expected
Definition: chan_mobile.c:461
char id[31]
Definition: chan_mobile.c:125
at_message_t response_to
Definition: chan_mobile.c:462
unsigned int needchup
Definition: chan_mobile.c:158
static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode)
Set the SMS mode.
Definition: chan_mobile.c:2625
unsigned int outgoing_sms
Definition: chan_mobile.c:155
Definition: chan_mobile.c:460
unsigned int incoming_sms
Definition: chan_mobile.c:156
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
struct msg_queue_entry::@6 entry

◆ handle_response_no_carrier()

static int handle_response_no_carrier ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle NO CARRIER messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3861 of file chan_mobile.c.

References AST_CONTROL_CONGESTION, ast_verb, mbl_pvt::id, mbl_queue_control(), and mbl_pvt::needchup.

Referenced by do_monitor_phone().

3862 {
3863  ast_verb(1, "[%s] mobile reports NO CARRIER\n", pvt->id);
3864  pvt->needchup = 1;
3866  return 0;
3867 }
#define ast_verb(level,...)
Definition: logger.h:463
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
char id[31]
Definition: chan_mobile.c:125
unsigned int needchup
Definition: chan_mobile.c:158

◆ handle_response_no_dialtone()

static int handle_response_no_dialtone ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle NO DIALTONE messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3846 of file chan_mobile.c.

References AST_CONTROL_CONGESTION, ast_verb, mbl_pvt::id, mbl_queue_control(), and mbl_pvt::needchup.

Referenced by do_monitor_phone().

3847 {
3848  ast_verb(1, "[%s] mobile reports NO DIALTONE\n", pvt->id);
3849  pvt->needchup = 1;
3851  return 0;
3852 }
#define ast_verb(level,...)
Definition: logger.h:463
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
char id[31]
Definition: chan_mobile.c:125
unsigned int needchup
Definition: chan_mobile.c:158

◆ handle_response_ok()

static int handle_response_ok ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle OK AT messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3273 of file chan_mobile.c.

References AST_CONTROL_PROGRESS, ast_debug, ast_verb, AT_A, AT_BRSF, AT_CHUP, AT_CIND, AT_CIND_TEST, AT_CLIP, AT_CMER, AT_CMGF, AT_CMGS, AT_CNMI, AT_CUSD, AT_D, AT_ECAM, at_msg2str(), AT_OK, AT_UNKNOWN, AT_VGS, AT_VTS, mbl_pvt::blackberry, hfp_cind::call, hfp_cind::callsetup, hfp_pvt::cind_map, hfp_pvt::cind_state, adapter_pvt::entry, msg_queue_entry::expected, mbl_pvt::has_sms, mbl_pvt::hfp, hfp_send_cind(), hfp_send_cind_test(), hfp_send_clip(), hfp_send_cmer(), hfp_send_cmgf(), hfp_send_cnmi(), hfp_send_ecam(), hfp_send_vgs(), mbl_pvt::id, hfp_pvt::initialized, mbl_queue_control(), msg_queue_free_and_pop(), msg_queue_head(), msg_queue_push(), mbl_pvt::needchup, mbl_pvt::outgoing, mbl_pvt::outgoing_sms, msg_queue_entry::response_to, hfp_cind::service, and mbl_pvt::timeout.

Referenced by do_monitor_phone().

3274 {
3275  struct msg_queue_entry *entry;
3276  if ((entry = msg_queue_head(pvt)) && entry->expected == AT_OK) {
3277  switch (entry->response_to) {
3278 
3279  /* initialization stuff */
3280  case AT_BRSF:
3281  ast_debug(1, "[%s] BSRF sent successfully\n", pvt->id);
3282 
3283  /* If this is a blackberry do CMER now, otherwise
3284  * continue with CIND as normal. */
3285  if (pvt->blackberry) {
3286  if (hfp_send_cmer(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMER)) {
3287  ast_debug(1, "[%s] error sending CMER\n", pvt->id);
3288  goto e_return;
3289  }
3290  } else {
3292  ast_debug(1, "[%s] error sending CIND test\n", pvt->id);
3293  goto e_return;
3294  }
3295  }
3296  break;
3297  case AT_CIND_TEST:
3298  ast_debug(1, "[%s] CIND test sent successfully\n", pvt->id);
3299 
3300  ast_debug(2, "[%s] call: %d\n", pvt->id, pvt->hfp->cind_map.call);
3301  ast_debug(2, "[%s] callsetup: %d\n", pvt->id, pvt->hfp->cind_map.callsetup);
3302  ast_debug(2, "[%s] service: %d\n", pvt->id, pvt->hfp->cind_map.service);
3303 
3304  if (hfp_send_cind(pvt->hfp) || msg_queue_push(pvt, AT_CIND, AT_CIND)) {
3305  ast_debug(1, "[%s] error requesting CIND state\n", pvt->id);
3306  goto e_return;
3307  }
3308  break;
3309  case AT_CIND:
3310  ast_debug(1, "[%s] CIND sent successfully\n", pvt->id);
3311 
3312  /* check if a call is active */
3313  if (pvt->hfp->cind_state[pvt->hfp->cind_map.call]) {
3314  ast_verb(3, "Bluetooth Device %s has a call in progress - delaying connection.\n", pvt->id);
3315  goto e_return;
3316  }
3317 
3318  /* If this is NOT a blackberry proceed with CMER,
3319  * otherwise send CLIP. */
3320  if (!pvt->blackberry) {
3321  if (hfp_send_cmer(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMER)) {
3322  ast_debug(1, "[%s] error sending CMER\n", pvt->id);
3323  goto e_return;
3324  }
3325  } else {
3326  if (hfp_send_clip(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CLIP)) {
3327  ast_debug(1, "[%s] error enabling calling line notification\n", pvt->id);
3328  goto e_return;
3329  }
3330  }
3331  break;
3332  case AT_CMER:
3333  ast_debug(1, "[%s] CMER sent successfully\n", pvt->id);
3334 
3335  /* If this is a blackberry proceed with the CIND test,
3336  * otherwise send CLIP. */
3337  if (pvt->blackberry) {
3339  ast_debug(1, "[%s] error sending CIND test\n", pvt->id);
3340  goto e_return;
3341  }
3342  } else {
3343  if (hfp_send_clip(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CLIP)) {
3344  ast_debug(1, "[%s] error enabling calling line notification\n", pvt->id);
3345  goto e_return;
3346  }
3347  }
3348  break;
3349  case AT_CLIP:
3350  ast_debug(1, "[%s] caling line indication enabled\n", pvt->id);
3351  if (hfp_send_ecam(pvt->hfp) || msg_queue_push(pvt, AT_OK, AT_ECAM)) {
3352  ast_debug(1, "[%s] error enabling Sony Ericsson call monitoring extensions\n", pvt->id);
3353  goto e_return;
3354  }
3355 
3356  break;
3357  case AT_ECAM:
3358  ast_debug(1, "[%s] Sony Ericsson call monitoring is active on device\n", pvt->id);
3359  if (hfp_send_vgs(pvt->hfp, 15) || msg_queue_push(pvt, AT_OK, AT_VGS)) {
3360  ast_debug(1, "[%s] error synchronizing gain settings\n", pvt->id);
3361  goto e_return;
3362  }
3363 
3364  pvt->timeout = -1;
3365  pvt->hfp->initialized = 1;
3366  ast_verb(3, "Bluetooth Device %s initialized and ready.\n", pvt->id);
3367 
3368  break;
3369  case AT_VGS:
3370  ast_debug(1, "[%s] volume level synchronization successful\n", pvt->id);
3371 
3372  /* set the SMS operating mode to text mode */
3373  if (pvt->has_sms) {
3374  if (hfp_send_cmgf(pvt->hfp, 1) || msg_queue_push(pvt, AT_OK, AT_CMGF)) {
3375  ast_debug(1, "[%s] error setting CMGF\n", pvt->id);
3376  goto e_return;
3377  }
3378  }
3379  break;
3380  case AT_CMGF:
3381  ast_debug(1, "[%s] sms text mode enabled\n", pvt->id);
3382  /* turn on SMS new message indication */
3383  if (hfp_send_cnmi(pvt->hfp) || msg_queue_push(pvt, AT_OK, AT_CNMI)) {
3384  ast_debug(1, "[%s] error setting CNMI\n", pvt->id);
3385  goto e_return;
3386  }
3387  break;
3388  case AT_CNMI:
3389  ast_debug(1, "[%s] sms new message indication enabled\n", pvt->id);
3390  pvt->has_sms = 1;
3391  break;
3392  /* end initialization stuff */
3393 
3394  case AT_A:
3395  ast_debug(1, "[%s] answer sent successfully\n", pvt->id);
3396  pvt->needchup = 1;
3397  break;
3398  case AT_D:
3399  ast_debug(1, "[%s] dial sent successfully\n", pvt->id);
3400  pvt->needchup = 1;
3401  pvt->outgoing = 1;
3403  break;
3404  case AT_CHUP:
3405  ast_debug(1, "[%s] successful hangup\n", pvt->id);
3406  break;
3407  case AT_CMGS:
3408  ast_debug(1, "[%s] successfully sent sms message\n", pvt->id);
3409  pvt->outgoing_sms = 0;
3410  break;
3411  case AT_VTS:
3412  ast_debug(1, "[%s] digit sent successfully\n", pvt->id);
3413  break;
3414  case AT_CUSD:
3415  ast_debug(1, "[%s] CUSD code sent successfully\n", pvt->id);
3416  break;
3417  case AT_UNKNOWN:
3418  default:
3419  ast_debug(1, "[%s] received OK for unhandled request: %s\n", pvt->id, at_msg2str(entry->response_to));
3420  break;
3421  }
3423  } else if (entry) {
3424  ast_debug(1, "[%s] received AT message 'OK' when expecting %s, ignoring\n", pvt->id, at_msg2str(entry->expected));
3425  } else {
3426  ast_debug(1, "[%s] received unexpected AT message 'OK'\n", pvt->id);
3427  }
3428  return 0;
3429 
3430 e_return:
3432  return -1;
3433 }
unsigned int blackberry
Definition: chan_mobile.c:144
static int hfp_send_cind(struct hfp_pvt *hfp)
Send the CIND read command.
Definition: chan_mobile.c:2525
int timeout
Definition: chan_mobile.c:139
static int hfp_send_cmer(struct hfp_pvt *hfp, int status)
Enable or disable indicator events reporting.
Definition: chan_mobile.c:2544
#define ast_verb(level,...)
Definition: logger.h:463
static int hfp_send_clip(struct hfp_pvt *hfp, int status)
Enable or disable calling line identification.
Definition: chan_mobile.c:2583
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int hfp_send_vgs(struct hfp_pvt *hfp, int value)
Send the current speaker gain level.
Definition: chan_mobile.c:2556
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
unsigned int has_sms
Definition: chan_mobile.c:141
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
int initialized
Definition: chan_mobile.c:346
static int mbl_queue_control(struct mbl_pvt *pvt, enum ast_control_frame_type control)
Definition: chan_mobile.c:1317
static const char * at_msg2str(at_message_t msg)
Get the string representation of the given AT message.
Definition: chan_mobile.c:2076
int callsetup
Definition: chan_mobile.c:333
static int hfp_send_cind_test(struct hfp_pvt *hfp)
Send the CIND test command.
Definition: chan_mobile.c:2534
int cind_state[16]
Definition: chan_mobile.c:350
at_message_t expected
Definition: chan_mobile.c:461
struct hfp_cind cind_map
Definition: chan_mobile.c:351
char id[31]
Definition: chan_mobile.c:125
at_message_t response_to
Definition: chan_mobile.c:462
unsigned int needchup
Definition: chan_mobile.c:158
static int hfp_send_cnmi(struct hfp_pvt *hfp)
Setup SMS new message indication.
Definition: chan_mobile.c:2636
static int hfp_send_ecam(struct hfp_pvt *hfp)
Enable Sony Erricson extensions / indications.
Definition: chan_mobile.c:2182
static int hfp_send_cmgf(struct hfp_pvt *hfp, int mode)
Set the SMS mode.
Definition: chan_mobile.c:2625
unsigned int outgoing_sms
Definition: chan_mobile.c:155
Definition: chan_mobile.c:460
int service
Definition: chan_mobile.c:331
unsigned int outgoing
Definition: chan_mobile.c:153
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032
struct msg_queue_entry::@6 entry

◆ handle_response_ring()

static int handle_response_ring ( struct mbl_pvt pvt,
char *  buf 
)
static

Handle RING messages.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3691 of file chan_mobile.c.

References ast_debug, AT_CLIP, AT_UNKNOWN, mbl_pvt::id, msg_queue_push(), and mbl_pvt::needcallerid.

Referenced by do_monitor_phone().

3692 {
3693  if (pvt->needcallerid) {
3694  ast_debug(1, "[%s] got ring while waiting for caller id\n", pvt->id);
3695  return msg_queue_push(pvt, AT_CLIP, AT_UNKNOWN);
3696  } else {
3697  return 0;
3698  }
3699 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
char id[31]
Definition: chan_mobile.c:125
unsigned int needcallerid
Definition: chan_mobile.c:157

◆ handle_sms_prompt()

static int handle_sms_prompt ( struct mbl_pvt pvt,
char *  buf 
)
static

Send an SMS message from the queue.

Parameters
pvta mbl_pvt structure
bufa null terminated buffer containing an AT message
Return values
0success
-1error

Definition at line 3780 of file chan_mobile.c.

References ast_debug, AT_CMGS, AT_OK, AT_SMS_PROMPT, msg_queue_entry::data, msg_queue_entry::expected, mbl_pvt::hfp, hfp_send_sms_text(), mbl_pvt::id, msg_queue_free_and_pop(), msg_queue_head(), and msg_queue_push().

Referenced by do_monitor_phone().

3781 {
3782  struct msg_queue_entry *msg;
3783  if (!(msg = msg_queue_head(pvt))) {
3784  ast_debug(1, "[%s] error, got sms prompt with no pending sms messages\n", pvt->id);
3785  return 0;
3786  }
3787 
3788  if (msg->expected != AT_SMS_PROMPT) {
3789  ast_debug(1, "[%s] error, got sms prompt but no pending sms messages\n", pvt->id);
3790  return 0;
3791  }
3792 
3793  if (hfp_send_sms_text(pvt->hfp, msg->data)
3794  || msg_queue_push(pvt, AT_OK, AT_CMGS)) {
3796  ast_debug(1, "[%s] error sending sms message\n", pvt->id);
3797  return 0;
3798  }
3799 
3801  return 0;
3802 }
static int hfp_send_sms_text(struct hfp_pvt *hfp, const char *message)
Send the text of an SMS message.
Definition: chan_mobile.c:2670
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct hfp_pvt * hfp
Definition: chan_mobile.c:130
static int msg_queue_push(struct mbl_pvt *pvt, at_message_t expect, at_message_t response_to)
Add an item to the back of the queue.
Definition: chan_mobile.c:2982
at_message_t expected
Definition: chan_mobile.c:461
char id[31]
Definition: chan_mobile.c:125
Definition: chan_mobile.c:460
static struct msg_queue_entry * msg_queue_head(struct mbl_pvt *pvt)
Get the head of a queue.
Definition: chan_mobile.c:3058
void * data
Definition: chan_mobile.c:463
static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
Remove an item from the front of the queue, and free it.
Definition: chan_mobile.c:3032

◆ headset_send_ring()

static int headset_send_ring ( const void *  data)
static

Definition at line 4102 of file chan_mobile.c.

References ast_debug, ast_mutex_lock, ast_mutex_unlock, hsp_send_ring(), mbl_pvt::id, mbl_pvt::lock, mbl_pvt::needring, and mbl_pvt::rfcomm_socket.

Referenced by mbl_call().

4103 {
4104  struct mbl_pvt *pvt = (struct mbl_pvt *) data;
4105  ast_mutex_lock(&pvt->lock);
4106  if (!pvt->needring) {
4107  ast_mutex_unlock(&pvt->lock);
4108  return 0;
4109  }
4110  ast_mutex_unlock(&pvt->lock);
4111 
4112  if (hsp_send_ring(pvt->rfcomm_socket)) {
4113  ast_debug(1, "[%s] error sending RING\n", pvt->id);
4114  return 0;
4115  }
4116  return 1;
4117 }
#define ast_mutex_lock(a)
Definition: lock.h:187
int rfcomm_socket
Definition: chan_mobile.c:132
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char id[31]
Definition: chan_mobile.c:125
static int hsp_send_ring(int rsock)
Send a RING unsolicited AT response.
Definition: chan_mobile.c:2966
ast_mutex_t lock
Definition: chan_mobile.c:121
unsigned int needring
Definition: chan_mobile.c:159
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ hfp_brsf2int()

static int hfp_brsf2int ( struct hfp_hf hf)
static

Convert a hfp_hf struct to a BRSF int.

Parameters
hfan hfp_hf brsf object
Returns
an integer representing the given brsf struct

Definition at line 2468 of file chan_mobile.c.

References hfp_hf::cid, hfp_hf::control, hfp_hf::cw, hfp_hf::ecnr, HFP_HF_CID, HFP_HF_CONTROL, HFP_HF_CW, HFP_HF_ECNR, HFP_HF_STATUS, HFP_HF_VOICE, HFP_HF_VOLUME, hfp_hf::status, hfp_hf::voice, and hfp_hf::volume.

Referenced by hfp_send_brsf().

2469 {
2470  int brsf = 0;
2471 
2472  brsf |= hf->ecnr ? HFP_HF_ECNR : 0;
2473  brsf |= hf->cw ? HFP_HF_CW : 0;
2474  brsf |= hf->cid ? HFP_HF_CID : 0;
2475  brsf |= hf->voice ? HFP_HF_VOICE : 0;
2476  brsf |= hf->volume ? HFP_HF_VOLUME : 0;
2477  brsf |= hf->status ? HFP_HF_STATUS : 0;
2478  brsf |= hf->control ? HFP_HF_CONTROL : 0;
2479 
2480  return brsf;
2481 }
int control
Definition: chan_mobile.c:309
#define HFP_HF_CID
Definition: chan_mobile.c:259
int status
Definition: chan_mobile.c:308
#define HFP_HF_STATUS
Definition: chan_mobile.c:262
int volume
Definition: chan_mobile.c:307
int ecnr
Definition: chan_mobile.c:303
int cid
Definition: chan_mobile.c:305
#define HFP_HF_VOICE
Definition: chan_mobile.c:260
int cw
Definition: chan_mobile.c:304
#define HFP_HF_CW
Definition: chan_mobile.c:258
#define HFP_HF_ECNR
Definition: chan_mobile.c:257
#define HFP_HF_CONTROL
Definition: chan_mobile.c:263
#define HFP_HF_VOLUME
Definition: chan_mobile.c:261
int voice
Definition: chan_mobile.c:306

◆ hfp_int2brsf()

static struct hfp_ag * hfp_int2brsf ( int  brsf,
struct hfp_ag ag 
)
static

Convert a BRSF int to an hfp_ag struct.

Parameters
brsfa brsf integer
aga AG (hfp_ag) brsf object
Returns
a pointer to the given hfp_ag object populated with the values from the given brsf integer

Definition at line 2490 of file chan_mobile.c.

References hfp_ag::control, hfp_ag::cw, hfp_ag::ecnr, hfp_ag::errors, HFP_AG_CONTROL, HFP_AG_CW, HFP_AG_ECNR, HFP_AG_ERRORS, HFP_AG_REJECT, HFP_AG_RING, HFP_AG_STATUS, HFP_AG_TAG, HFP_AG_VOICE, hfp_ag::reject, hfp_ag::ring, hfp_ag::status, hfp_ag::tag, and hfp_ag::voice.

Referenced by hfp_parse_brsf().

2491 {
2492  ag->cw = brsf & HFP_AG_CW ? 1 : 0;
2493  ag->ecnr = brsf & HFP_AG_ECNR ? 1 : 0;
2494  ag->voice = brsf & HFP_AG_VOICE ? 1 : 0;
2495  ag->ring = brsf & HFP_AG_RING ? 1 : 0;
2496  ag->tag = brsf & HFP_AG_TAG ? 1 : 0;
2497  ag->reject = brsf & HFP_AG_REJECT ? 1 : 0;
2498  ag->status = brsf & HFP_AG_STATUS ? 1 : 0;
2499  ag->control = brsf & HFP_AG_CONTROL ? 1 : 0;
2500  ag->errors = brsf & HFP_AG_ERRORS ? 1 : 0;
2501 
2502  return ag;
2503 }
#define HFP_AG_ERRORS
Definition: chan_mobile.c:273
int ecnr
Definition: chan_mobile.c:317
#define HFP_AG_ECNR
Definition: chan_mobile.c:266
#define HFP_AG_CONTROL
Definition: chan_mobile.c:272
#define HFP_AG_CW
Definition: chan_mobile.c:265
int reject
Definition: chan_mobile.c:321
#define HFP_AG_REJECT
Definition: chan_mobile.c:270
int control
Definition: chan_mobile.c:323
#define HFP_AG_RING
Definition: chan_mobile.c:268
int ring
Definition: chan_mobile.c:319
#define HFP_AG_VOICE
Definition: chan_mobile.c:267
int cw
Definition: chan_mobile.c:316
int voice
Definition: chan_mobile.c:318
int errors
Definition: chan_mobile.c:324
int tag
Definition: chan_mobile.c:320
#define HFP_AG_STATUS
Definition: chan_mobile.c:271
int status
Definition: chan_mobile.c:322
#define HFP_AG_TAG
Definition: chan_mobile.c:269

◆ hfp_parse_brsf()

static int hfp_parse_brsf ( struct hfp_pvt hfp,
const char *  buf 
)
static

Parse BRSF data.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)

Definition at line 2724 of file chan_mobile.c.

References hfp_pvt::brsf, and hfp_int2brsf().

Referenced by handle_response_brsf().

2725 {
2726  int brsf;
2727 
2728  if (!sscanf(buf, "+BRSF:%d", &brsf))
2729  return -1;
2730 
2731  hfp_int2brsf(brsf, &hfp->brsf);
2732 
2733  return 0;
2734 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct hfp_ag * hfp_int2brsf(int brsf, struct hfp_ag *ag)
Convert a BRSF int to an hfp_ag struct.
Definition: chan_mobile.c:2490
struct hfp_ag brsf
Definition: chan_mobile.c:348

◆ hfp_parse_ciev()

static int hfp_parse_ciev ( struct hfp_pvt hfp,
char *  buf,
int *  value 
)
static

Parse a CIEV event.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
valuea pointer to an int to store the event value in (can be NULL)
Returns
0 on error (parse error, or unknown event) or a HFP_CIND_* value on success

Definition at line 2195 of file chan_mobile.c.

References ARRAY_LEN, ast_debug, hfp_pvt::cind_index, hfp_pvt::cind_state, HFP_CIND_NONE, mbl_pvt::id, hfp_pvt::owner, and value.

Referenced by handle_response_ciev().

2196 {
2197  int i, v;
2198  if (!value)
2199  value = &v;
2200 
2201  if (!sscanf(buf, "+CIEV: %d,%d", &i, value)) {
2202  ast_debug(2, "[%s] error parsing CIEV event '%s'\n", hfp->owner->id, buf);
2203  return HFP_CIND_NONE;
2204  }
2205 
2206  if (i >= ARRAY_LEN(hfp->cind_state)) {
2207  ast_debug(2, "[%s] CIEV event index too high (%s)\n", hfp->owner->id, buf);
2208  return HFP_CIND_NONE;
2209  }
2210 
2211  hfp->cind_state[i] = *value;
2212  return hfp->cind_index[i];
2213 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define HFP_CIND_NONE
Definition: chan_mobile.c:276
int cind_index[16]
Definition: chan_mobile.c:349
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int value
Definition: syslog.c:37
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mbl_pvt * owner
Definition: chan_mobile.c:345
int cind_state[16]
Definition: chan_mobile.c:350
char id[31]
Definition: chan_mobile.c:125

◆ hfp_parse_cind()

static int hfp_parse_cind ( struct hfp_pvt hfp,
char *  buf 
)
static

Read the result of the AT+CIND? command.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
Note
hfp_send_cind_test() and hfp_parse_cind_test() should be called at least once before this function is called.

Definition at line 2768 of file chan_mobile.c.

References hfp_parse_cind_indicator(), indicator, NULL, and state.

Referenced by handle_response_cind().

2769 {
2770  int i, state, group;
2771  size_t s;
2772  char *indicator = NULL;
2773 
2774  /* parse current state of all of our indicators. The list is in the
2775  * following format:
2776  * +CIND: 1,0,2,0,0,0,0
2777  */
2778  group = 0;
2779  state = 0;
2780  s = strlen(buf);
2781  for (i = 0; i < s; i++) {
2782  switch (state) {
2783  case 0: /* search for start of the status indicators (a space) */
2784  if (buf[i] == ' ') {
2785  group++;
2786  state++;
2787  }
2788  break;
2789  case 1: /* mark this indicator */
2790  indicator = &buf[i];
2791  state++;
2792  break;
2793  case 2: /* search for the start of the next indicator (a comma) */
2794  if (buf[i] == ',') {
2795  buf[i] = '\0';
2796 
2797  hfp_parse_cind_indicator(hfp, group, indicator);
2798 
2799  group++;
2800  state = 1;
2801  }
2802  break;
2803  }
2804  }
2805 
2806  /* store the last indicator */
2807  if (state == 2)
2808  hfp_parse_cind_indicator(hfp, group, indicator);
2809 
2810  return 0;
2811 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int indicator
#define NULL
Definition: resample.c:96
static int hfp_parse_cind_indicator(struct hfp_pvt *hfp, int group, char *indicator)
Parse and store the given indicator.
Definition: chan_mobile.c:2742
int group
Definition: chan_mobile.c:126

◆ hfp_parse_cind_indicator()

static int hfp_parse_cind_indicator ( struct hfp_pvt hfp,
int  group,
char *  indicator 
)
static

Parse and store the given indicator.

Parameters
hfpan hfp_pvt struct
groupthe indicator group
indicatorthe indicator to parse

Definition at line 2742 of file chan_mobile.c.

References ARRAY_LEN, ast_debug, hfp_pvt::cind_state, and value.

Referenced by hfp_parse_cind().

2743 {
2744  int value;
2745 
2746  /* store the current indicator */
2747  if (group >= ARRAY_LEN(hfp->cind_state)) {
2748  ast_debug(1, "ignoring CIND state '%s' for group %d, we only support up to %d indicators\n", indicator, group, (int) sizeof(hfp->cind_state));
2749  return -1;
2750  }
2751 
2752  if (!sscanf(indicator, "%d", &value)) {
2753  ast_debug(1, "error parsing CIND state '%s' for group %d\n", indicator, group);
2754  return -1;
2755  }
2756 
2757  hfp->cind_state[group] = value;
2758  return 0;
2759 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int indicator
int value
Definition: syslog.c:37
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int cind_state[16]
Definition: chan_mobile.c:350
int group
Definition: chan_mobile.c:126

◆ hfp_parse_cind_test()

static int hfp_parse_cind_test ( struct hfp_pvt hfp,
char *  buf 
)
static

Parse the result of the AT+CIND=? command.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)

Definition at line 2818 of file chan_mobile.c.

References ast_debug, hfp_cind::battchg, hfp_cind::call, hfp_cind::callheld, hfp_cind::callsetup, hfp_pvt::cind_index, hfp_pvt::cind_map, HFP_CIND_BATTCHG, HFP_CIND_CALL, HFP_CIND_CALLHELD, HFP_CIND_CALLSETUP, HFP_CIND_ROAM, HFP_CIND_SERVICE, HFP_CIND_SIGNAL, HFP_CIND_UNKNOWN, indicator, mbl_pvt::no_callsetup, hfp_pvt::nocallsetup, NULL, hfp_pvt::owner, hfp_cind::roam, hfp_cind::service, hfp_cind::signal, and state.

Referenced by handle_response_cind().

2819 {
2820  int i, state, group;
2821  size_t s;
2822  char *indicator = NULL;
2823 
2824  hfp->nocallsetup = 1;
2825 
2826  /* parse the indications list. It is in the follwing format:
2827  * +CIND: ("ind1",(0-1)),("ind2",(0-5))
2828  */
2829  group = 0;
2830  state = 0;
2831  s = strlen(buf);
2832  for (i = 0; i < s; i++) {
2833  switch (state) {
2834  case 0: /* search for start of indicator block */
2835  if (buf[i] == '(') {
2836  group++;
2837  state++;
2838  }
2839  break;
2840  case 1: /* search for '"' in indicator block */
2841  if (buf[i] == '"') {
2842  state++;
2843  }
2844  break;
2845  case 2: /* mark the start of the indicator name */
2846  indicator = &buf[i];
2847  state++;
2848  break;
2849  case 3: /* look for the end of the indicator name */
2850  if (buf[i] == '"') {
2851  buf[i] = '\0';
2852  state++;
2853  }
2854  break;
2855  case 4: /* find the start of the value range */
2856  if (buf[i] == '(') {
2857  state++;
2858  }
2859  break;
2860  case 5: /* mark the start of the value range */
2861  state++;
2862  break;
2863  case 6: /* find the end of the value range */
2864  if (buf[i] == ')') {
2865  buf[i] = '\0';
2866  state++;
2867  }
2868  break;
2869  case 7: /* process the values we found */
2870  if (group < sizeof(hfp->cind_index)) {
2871  if (!strcmp(indicator, "service")) {
2872  hfp->cind_map.service = group;
2874  } else if (!strcmp(indicator, "call")) {
2875  hfp->cind_map.call = group;
2876  hfp->cind_index[group] = HFP_CIND_CALL;
2877  } else if (!strcmp(indicator, "callsetup")) {
2878  hfp->nocallsetup = 0;
2879  hfp->cind_map.callsetup = group;
2881  } else if (!strcmp(indicator, "call_setup")) { /* non standard call setup identifier */
2882  hfp->nocallsetup = 0;
2883  hfp->cind_map.callsetup = group;
2885  } else if (!strcmp(indicator, "callheld")) {
2886  hfp->cind_map.callheld = group;
2888  } else if (!strcmp(indicator, "signal")) {
2889  hfp->cind_map.signal = group;
2891  } else if (!strcmp(indicator, "roam")) {
2892  hfp->cind_map.roam = group;
2893  hfp->cind_index[group] = HFP_CIND_ROAM;
2894  } else if (!strcmp(indicator, "battchg")) {
2895  hfp->cind_map.battchg = group;
2897  } else {
2899  ast_debug(2, "ignoring unknown CIND indicator '%s'\n", indicator);
2900  }
2901  } else {
2902  ast_debug(1, "can't store indicator %d (%s), we only support up to %d indicators", group, indicator, (int) sizeof(hfp->cind_index));
2903  }
2904 
2905  state = 0;
2906  break;
2907  }
2908  }
2909 
2910  hfp->owner->no_callsetup = hfp->nocallsetup;
2911 
2912  return 0;
2913 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
#define HFP_CIND_CALL
Definition: chan_mobile.c:278
#define HFP_CIND_BATTCHG
Definition: chan_mobile.c:283
#define HFP_CIND_SIGNAL
Definition: chan_mobile.c:281
#define HFP_CIND_ROAM
Definition: chan_mobile.c:282
int cind_index[16]
Definition: chan_mobile.c:349
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int indicator
#define HFP_CIND_CALLSETUP
Definition: chan_mobile.c:279
#define HFP_CIND_UNKNOWN
Definition: chan_mobile.c:275
int nocallsetup
Definition: chan_mobile.c:347
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mbl_pvt * owner
Definition: chan_mobile.c:345
unsigned int no_callsetup
Definition: chan_mobile.c:140
int battchg
Definition: chan_mobile.c:337
int callheld
Definition: chan_mobile.c:334
int callsetup
Definition: chan_mobile.c:333
struct hfp_cind cind_map
Definition: chan_mobile.c:351
int signal
Definition: chan_mobile.c:335
#define HFP_CIND_CALLHELD
Definition: chan_mobile.c:280
int service
Definition: chan_mobile.c:331
#define HFP_CIND_SERVICE
Definition: chan_mobile.c:277
int group
Definition: chan_mobile.c:126

◆ hfp_parse_clip()

static struct cidinfo hfp_parse_clip ( struct hfp_pvt hfp,
char *  buf 
)
static

Parse a CLIP event.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
Note
buf will be modified when the CID string is parsed
Returns
a cidinfo structure pointing to the cnam and cnum data in buf. On parse errors, either or both pointers will point to null strings

Definition at line 2224 of file chan_mobile.c.

References ARRAY_LEN, ast_debug, ast_isphonenumber(), ast_strip_quoted(), buf, cidinfo::cnam, cidinfo::cnum, NULL, and parse_next_token().

Referenced by handle_response_clip().

2225 {
2226  int i;
2227  int tokens[6];
2228  char *cnamtmp;
2229  char delim = ' '; /* First token terminates with space */
2230  int invalid = 0; /* Number of invalid chars in cnam */
2231  struct cidinfo cidinfo = { NULL, NULL };
2232 
2233  /* parse clip info in the following format:
2234  * +CLIP: "123456789",128,...
2235  */
2236  ast_debug(3, "[%s] hfp_parse_clip is processing \"%s\"\n", hfp->owner->id, buf);
2237  tokens[0] = 0; /* First token starts in position 0 */
2238  for (i = 1; i < ARRAY_LEN(tokens); i++) {
2239  tokens[i] = parse_next_token(buf, tokens[i - 1], delim);
2240  delim = ','; /* Subsequent tokens terminate with comma */
2241  }
2242  ast_debug(3, "[%s] hfp_parse_clip found tokens: 0=%s, 1=%s, 2=%s, 3=%s, 4=%s, 5=%s\n",
2243  hfp->owner->id, &buf[tokens[0]], &buf[tokens[1]], &buf[tokens[2]],
2244  &buf[tokens[3]], &buf[tokens[4]], &buf[tokens[5]]);
2245 
2246  /* Clean up cnum, and make sure it is legitimate since it is untrusted. */
2247  cidinfo.cnum = ast_strip_quoted(&buf[tokens[1]], "\"", "\"");
2248  if (!ast_isphonenumber(cidinfo.cnum)) {
2249  ast_debug(1, "[%s] hfp_parse_clip invalid cidinfo.cnum data \"%s\" - deleting\n",
2250  hfp->owner->id, cidinfo.cnum);
2251  cidinfo.cnum = "";
2252  }
2253 
2254  /*
2255  * Some docs say tokens 2 and 3 including the commas are optional.
2256  * If absent, that would move CNAM back to token 3.
2257  */
2258  cidinfo.cnam = &buf[tokens[5]]; /* Assume it's in token 5 */
2259  if (buf[tokens[5]] == '\0' && buf[tokens[4]] == '\0') {
2260  /* Tokens 4 and 5 are empty. See if token 3 looks like CNAM (starts with ") */
2261  i = tokens[3];
2262  while (buf[i] == ' ') { /* Find the first non-blank */
2263  i++;
2264  }
2265  if (buf[i] == '"') {
2266  /* Starts with quote. Use this for CNAM. */
2267  cidinfo.cnam = &buf[i];
2268  }
2269  }
2270 
2271  /* Clean up CNAM. */
2272  cidinfo.cnam = ast_strip_quoted(cidinfo.cnam, "\"", "\"");
2273  for (cnamtmp = cidinfo.cnam; *cnamtmp != '\0'; cnamtmp++) {
2274  if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789-,abcdefghijklmnopqrstuvwxyz_", *cnamtmp)) {
2275  *cnamtmp = '_'; /* Invalid. Replace with underscore. */
2276  invalid++;
2277  }
2278  }
2279  if (invalid) {
2280  ast_debug(2, "[%s] hfp_parse_clip replaced %d invalid byte(s) in cnam data\n",
2281  hfp->owner->id, invalid);
2282  }
2283  ast_debug(2, "[%s] hfp_parse_clip returns cnum=%s and cnam=%s\n",
2284  hfp->owner->id, cidinfo.cnum, cidinfo.cnam);
2285 
2286  return cidinfo;
2287 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
static int parse_next_token(char string[], const int start, const char delim)
Terminate current token and return an index to start of the next token.
Definition: chan_mobile.c:2297
char * cnam
Definition: chan_mobile.c:169
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: main/utils.c:1639
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mbl_pvt * owner
Definition: chan_mobile.c:345
char id[31]
Definition: chan_mobile.c:125
int ast_isphonenumber(const char *n)
Check if a string consists only of digits and + #.
Definition: callerid.c:998
char * cnum
Definition: chan_mobile.c:168

◆ hfp_parse_cmgr()

static int hfp_parse_cmgr ( struct hfp_pvt hfp,
char *  buf,
char **  from_number,
char **  text 
)
static

Parse a CMGR message.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
from_numbera pointer to a char pointer which will store the from number
texta pointer to a char pointer which will store the message text
Note
buf will be modified when the CMGR message is parsed
Return values
-1parse error
0success

Definition at line 2352 of file chan_mobile.c.

References state.

Referenced by handle_response_cmgr().

2353 {
2354  int i, state;
2355  size_t s;
2356 
2357  /* parse cmgr info in the following format:
2358  * +CMGR: <msg status>,"+123456789",...\r\n
2359  * <message text>
2360  */
2361  state = 0;
2362  s = strlen(buf);
2363  for (i = 0; i < s && state != 6; i++) {
2364  switch (state) {
2365  case 0: /* search for start of the number section (,) */
2366  if (buf[i] == ',') {
2367  state++;
2368  }
2369  break;
2370  case 1: /* find the opening quote (") */
2371  if (buf[i] == '"') {
2372  state++;
2373  }
2374  break;
2375  case 2: /* mark the start of the number */
2376  if (from_number) {
2377  *from_number = &buf[i];
2378  state++;
2379  }
2380  /* fall through */
2381  case 3: /* search for the end of the number (") */
2382  if (buf[i] == '"') {
2383  buf[i] = '\0';
2384  state++;
2385  }
2386  break;
2387  case 4: /* search for the start of the message text (\n) */
2388  if (buf[i] == '\n') {
2389  state++;
2390  }
2391  break;
2392  case 5: /* mark the start of the message text */
2393  if (text) {
2394  *text = &buf[i];
2395  state++;
2396  }
2397  break;
2398  }
2399  }
2400 
2401  if (state != 6) {
2402  return -1;
2403  }
2404 
2405  return 0;
2406 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * text
Definition: app_queue.c:1508

◆ hfp_parse_cmti()

static int hfp_parse_cmti ( struct hfp_pvt hfp,
char *  buf 
)
static

Parse a CMTI notification.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
Note
buf will be modified when the CMTI message is parsed
Returns
-1 on error (parse error) or the index of the new sms message

Definition at line 2326 of file chan_mobile.c.

References ast_debug, mbl_pvt::id, and hfp_pvt::owner.

Referenced by handle_response_cmti().

2327 {
2328  int index = -1;
2329 
2330  /* parse cmti info in the following format:
2331  * +CMTI: <mem>,<index>
2332  */
2333  if (!sscanf(buf, "+CMTI: %*[^,],%d", &index)) {
2334  ast_debug(2, "[%s] error parsing CMTI event '%s'\n", hfp->owner->id, buf);
2335  return -1;
2336  }
2337 
2338  return index;
2339 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mbl_pvt * owner
Definition: chan_mobile.c:345
char id[31]
Definition: chan_mobile.c:125

◆ hfp_parse_cusd()

static char * hfp_parse_cusd ( struct hfp_pvt hfp,
char *  buf 
)
static

Parse a CUSD answer.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
Note
buf will be modified when the CUSD string is parsed
Returns
NULL on error (parse error) or a pointer to the cusd message information in buf

Definition at line 2416 of file chan_mobile.c.

References NULL.

Referenced by handle_response_cusd().

2417 {
2418  int i, message_start, message_end;
2419  char *cusd;
2420  size_t s;
2421 
2422  /* parse cusd message in the following format:
2423  * +CUSD: 0,"100,00 EURO, valid till 01.01.2010, you are using tariff "Mega Tariff". More informations *111#."
2424  */
2425  message_start = 0;
2426  message_end = 0;
2427  s = strlen(buf);
2428 
2429  /* Find the start of the message (") */
2430  for (i = 0; i < s; i++) {
2431  if (buf[i] == '"') {
2432  message_start = i + 1;
2433  break;
2434  }
2435  }
2436 
2437  if (message_start == 0 || message_start >= s) {
2438  return NULL;
2439  }
2440 
2441  /* Find the end of the message (") */
2442  for (i = s; i > 0; i--) {
2443  if (buf[i] == '"') {
2444  message_end = i;
2445  break;
2446  }
2447  }
2448 
2449  if (message_end == 0) {
2450  return NULL;
2451  }
2452 
2453  if (message_start >= message_end) {
2454  return NULL;
2455  }
2456 
2457  cusd = &buf[message_start];
2458  buf[message_end] = '\0';
2459 
2460  return cusd;
2461 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96

◆ hfp_parse_ecav()

static int hfp_parse_ecav ( struct hfp_pvt hfp,
char *  buf 
)
static

Parse a ECAV event.

Parameters
hfpan hfp_pvt struct
bufthe buffer to parse (null terminated)
Returns
-1 on error (parse error) or a ECAM value on success

Example string: *ECAV: <ccid>,<ccstatus>,<calltype>[,<processid>] [,exitcause][,<number>,<type>]

Example indicating busy: *ECAV: 1,7,1

Definition at line 2164 of file chan_mobile.c.

References ast_debug, mbl_pvt::id, and hfp_pvt::owner.

Referenced by do_monitor_phone().

2165 {
2166  int ccid = 0;
2167  int ccstatus = 0;
2168  int calltype = 0;
2169 
2170  if (!sscanf(buf, "*ECAV: %2d,%2d,%2d", &ccid, &ccstatus, &calltype)) {
2171  ast_debug(1, "[%s] error parsing ECAV event '%s'\n", hfp->owner->id, buf);
2172  return -1;
2173  }
2174 
2175  return ccstatus;
2176 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct mbl_pvt * owner
Definition: chan_mobile.c:345
char id[31]
Definition: chan_mobile.c:125

◆ hfp_send_ata()

static int hfp_send_ata ( struct hfp_pvt hfp)
static

Send ATA.

Parameters
hfpan hfp_pvt struct

Definition at line 2702 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by mbl_answer().

2703 {
2704  return rfcomm_write(hfp->rsock, "ATA\r");
2705 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_atd()

static int hfp_send_atd ( struct hfp_pvt hfp,
const char *  number 
)
static

Send ATD.

Parameters
hfpan hfp_pvt struct
numberthe number to send

Definition at line 2691 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by mbl_call().

2692 {
2693  char cmd[64];
2694  snprintf(cmd, sizeof(cmd), "ATD%s;\r", number);
2695  return rfcomm_write(hfp->rsock, cmd);
2696 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
Number structure.
Definition: app_followme.c:154

◆ hfp_send_brsf()

static int hfp_send_brsf ( struct hfp_pvt hfp,
struct hfp_hf brsf 
)
static

Send a BRSF request.

Parameters
hfpan hfp_pvt struct
brsfan hfp_hf brsf struct
Return values
0on success
-1on error

Definition at line 2514 of file chan_mobile.c.

References hfp_brsf2int(), rfcomm_write(), and hfp_pvt::rsock.

Referenced by do_monitor_phone().

2515 {
2516  char cmd[32];
2517  snprintf(cmd, sizeof(cmd), "AT+BRSF=%d\r", hfp_brsf2int(brsf));
2518  return rfcomm_write(hfp->rsock, cmd);
2519 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
static int hfp_brsf2int(struct hfp_hf *hf)
Convert a hfp_hf struct to a BRSF int.
Definition: chan_mobile.c:2468

◆ hfp_send_chup()

static int hfp_send_chup ( struct hfp_pvt hfp)
static

Send AT+CHUP.

Parameters
hfpan hfp_pvt struct

Definition at line 2681 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_clip(), and mbl_hangup().

2682 {
2683  return rfcomm_write(hfp->rsock, "AT+CHUP\r");
2684 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_cind()

static int hfp_send_cind ( struct hfp_pvt hfp)
static

Send the CIND read command.

Parameters
hfpan hfp_pvt struct

Definition at line 2525 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_ok().

2526 {
2527  return rfcomm_write(hfp->rsock, "AT+CIND?\r");
2528 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_cind_test()

static int hfp_send_cind_test ( struct hfp_pvt hfp)
static

Send the CIND test command.

Parameters
hfpan hfp_pvt struct

Definition at line 2534 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_ok().

2535 {
2536  return rfcomm_write(hfp->rsock, "AT+CIND=?\r");
2537 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_clip()

static int hfp_send_clip ( struct hfp_pvt hfp,
int  status 
)
static

Enable or disable calling line identification.

Parameters
hfpan hfp_pvt struct
statusenable or disable calling line identification (should be 1 or 0)

Definition at line 2583 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_ok().

2584 {
2585  char cmd[32];
2586  snprintf(cmd, sizeof(cmd), "AT+CLIP=%d\r", status ? 1 : 0);
2587  return rfcomm_write(hfp->rsock, cmd);
2588 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
jack_status_t status
Definition: app_jack.c:146

◆ hfp_send_cmer()

static int hfp_send_cmer ( struct hfp_pvt hfp,
int  status 
)
static

Enable or disable indicator events reporting.

Parameters
hfpan hfp_pvt struct
statusenable or disable events reporting (should be 1 or 0)

Definition at line 2544 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_ok().

2545 {
2546  char cmd[32];
2547  snprintf(cmd, sizeof(cmd), "AT+CMER=3,0,0,%d\r", status ? 1 : 0);
2548  return rfcomm_write(hfp->rsock, cmd);
2549 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
jack_status_t status
Definition: app_jack.c:146

◆ hfp_send_cmgf()

static int hfp_send_cmgf ( struct hfp_pvt hfp,
int  mode 
)
static

Set the SMS mode.

Parameters
hfpan hfp_pvt struct
modethe sms mode (0 = PDU, 1 = Text)

Definition at line 2625 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_error(), and handle_response_ok().

2626 {
2627  char cmd[32];
2628  snprintf(cmd, sizeof(cmd), "AT+CMGF=%d\r", mode);
2629  return rfcomm_write(hfp->rsock, cmd);
2630 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_cmgr()

static int hfp_send_cmgr ( struct hfp_pvt hfp,
int  index 
)
static

Read an SMS message.

Parameters
hfpan hfp_pvt struct
indexthe location of the requested message

Definition at line 2646 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_cmti().

2647 {
2648  char cmd[32];
2649  snprintf(cmd, sizeof(cmd), "AT+CMGR=%d\r", index);
2650  return rfcomm_write(hfp->rsock, cmd);
2651 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_cmgs()

static int hfp_send_cmgs ( struct hfp_pvt hfp,
const char *  number 
)
static

Start sending an SMS message.

Parameters
hfpan hfp_pvt struct
numberthe destination of the message

Definition at line 2658 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by mbl_sendsms_exec().

2659 {
2660  char cmd[64];
2661  snprintf(cmd, sizeof(cmd), "AT+CMGS=\"%s\"\r", number);
2662  return rfcomm_write(hfp->rsock, cmd);
2663 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
Number structure.
Definition: app_followme.c:154

◆ hfp_send_cnmi()

static int hfp_send_cnmi ( struct hfp_pvt hfp)
static

Setup SMS new message indication.

Parameters
hfpan hfp_pvt struct

Definition at line 2636 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_ok().

2637 {
2638  return rfcomm_write(hfp->rsock, "AT+CNMI=2,1,0,0,0\r");
2639 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_cusd()

static int hfp_send_cusd ( struct hfp_pvt hfp,
const char *  code 
)
static

Send CUSD.

Parameters
hfpan hfp_pvt struct
codethe CUSD code to send

Definition at line 2712 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_cli_mobile_cusd().

2713 {
2714  char cmd[128];
2715  snprintf(cmd, sizeof(cmd), "AT+CUSD=1,\"%s\",15\r", code);
2716  return rfcomm_write(hfp->rsock, cmd);
2717 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_dtmf()

static int hfp_send_dtmf ( struct hfp_pvt hfp,
char  digit 
)
static

Send a DTMF command.

Parameters
hfpan hfp_pvt struct
digitthe dtmf digit to send
Returns
the result of rfcomm_write() or -1 on an invalid digit being sent

Definition at line 2596 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by mbl_digit_end().

2597 {
2598  char cmd[10];
2599 
2600  switch(digit) {
2601  case '0':
2602  case '1':
2603  case '2':
2604  case '3':
2605  case '4':
2606  case '5':
2607  case '6':
2608  case '7':
2609  case '8':
2610  case '9':
2611  case '*':
2612  case '#':
2613  snprintf(cmd, sizeof(cmd), "AT+VTS=%c\r", digit);
2614  return rfcomm_write(hfp->rsock, cmd);
2615  default:
2616  return -1;
2617  }
2618 }
char digit
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_ecam()

static int hfp_send_ecam ( struct hfp_pvt hfp)
static

Enable Sony Erricson extensions / indications.

Parameters
hfpan hfp_pvt struct

Definition at line 2182 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_response_ok().

2183 {
2184  return rfcomm_write(hfp->rsock, "AT*ECAM=1\r");
2185 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_sms_text()

static int hfp_send_sms_text ( struct hfp_pvt hfp,
const char *  message 
)
static

Send the text of an SMS message.

Parameters
hfpan hfp_pvt struct
messagethe text of the message

Definition at line 2670 of file chan_mobile.c.

References rfcomm_write(), and hfp_pvt::rsock.

Referenced by handle_sms_prompt().

2671 {
2672  char cmd[162];
2673  snprintf(cmd, sizeof(cmd), "%.160s\x1a", message);
2674  return rfcomm_write(hfp->rsock, cmd);
2675 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hfp_send_vgs()

static int hfp_send_vgs ( struct hfp_pvt hfp,
int  value 
)
static

Send the current speaker gain level.

Parameters
hfpan hfp_pvt struct
valuethe value to send (must be between 0 and 15)

Definition at line 2556 of file chan_mobile.c.

References rfcomm_write(), hfp_pvt::rsock, and value.

Referenced by handle_response_error(), and handle_response_ok().

2557 {
2558  char cmd[32];
2559  snprintf(cmd, sizeof(cmd), "AT+VGS=%d\r", value);
2560  return rfcomm_write(hfp->rsock, cmd);
2561 }
int rsock
Definition: chan_mobile.c:352
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436
int value
Definition: syslog.c:37

◆ hsp_send_error()

static int hsp_send_error ( int  rsock)
static

Send an ERROR AT response.

Parameters
rsockthe rfcomm socket to use

Definition at line 2933 of file chan_mobile.c.

References rfcomm_write().

Referenced by do_monitor_headset().

2934 {
2935  return rfcomm_write(rsock, "\r\nERROR\r\n");
2936 }
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hsp_send_ok()

static int hsp_send_ok ( int  rsock)
static

Send an OK AT response.

Parameters
rsockthe rfcomm socket to use

Definition at line 2924 of file chan_mobile.c.

References rfcomm_write().

Referenced by do_monitor_headset().

2925 {
2926  return rfcomm_write(rsock, "\r\nOK\r\n");
2927 }
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hsp_send_ring()

static int hsp_send_ring ( int  rsock)
static

Send a RING unsolicited AT response.

Parameters
rsockthe rfcomm socket to use

Definition at line 2966 of file chan_mobile.c.

References rfcomm_write().

Referenced by headset_send_ring(), and mbl_call().

2967 {
2968  return rfcomm_write(rsock, "\r\nRING\r\n");
2969 }
static int rfcomm_write(int rsock, char *buf)
Write to an rfcomm socket.
Definition: chan_mobile.c:1436

◆ hsp_send_vgm()

static int hsp_send_vgm ( int  rsock,
int  gain 
)
static

Send a microphone gain unsolicited AT response.

Parameters
rsockthe rfcomm socket to use
gainthe microphone gain value

Definition at line 2955 of file chan_mobile.c.

References rfcomm_write().

Referenced by do_monitor_headset().

2956 {
2957  char cmd[32];
2958  snprintf(cmd, sizeof(cmd), "\r\n+VGM=%d\r\n", gain);
2959  return