From cae744afbe89e9e8dfd3384dbaad54db20013e3d Mon Sep 17 00:00:00 2001
From: Grzegorz Sluja <grzegorz.sluja@iopsys.eu>
Date: Wed, 8 Sep 2021 11:04:48 +0200
Subject: [PATCH] Implementation for new ubus call to get call_status
Call Status for each line can be get by:
ubus call asterisk call_status '{ "line" : X }', where X is line:
{0, 1, 2, or 3}
callStatus is set in chan_brcm according to TR-104 requirements:
Idle: no ongoing calls
Dialing: the process of collecting digits for the calling number in an outgoing call, and ringing in outgoing call.
Delivered: N/A
Connected: a call is established
Alerting: ringing when an incoming call is received
Disconnected: the remote party has ended a call. but the local party has not gone on-hook.
---
channels/chan_brcm.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
channels/chan_brcm.h | 2 ++
2 files changed, 65 insertions(+)
diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c
index 1e82c66..ad9b5f5 100644
--- a/channels/chan_brcm.c
+++ b/channels/chan_brcm.c
@@ -211,6 +211,11 @@ enum {
__EVENT_MAX,
};
+enum {
+ CALL_STATUS_LINE_ID,
+ __CALL_STATUS_MAX,
+};
+
enum { // New ubus objects in global context
OBJ_ID, // UBUS ID of object
OBJ_PATH, // String path of object
@@ -265,6 +270,10 @@ static const struct blobmsg_policy asterisk_event_policy[] = {
[EVENT_LINE_ID] = { .name = "line", .type = BLOBMSG_TYPE_INT32 },
};
+static const struct blobmsg_policy asterisk_call_status_policy[] = {
+ [CALL_STATUS_LINE_ID] = { .name = "line", .type = BLOBMSG_TYPE_INT32 },
+};
+
static const struct blobmsg_policy new_obj_policy[] = {
[OBJ_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, // UBUS ID of object
[OBJ_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, // String path of object
@@ -828,6 +837,7 @@ static int brcm_call(struct ast_channel *chan, const char *dest, int timeout)
pvt_lock(sub->parent, "brcm_call");
p = sub->parent;
+ strncpy(p->callStatus, "Alerting", CALL_STATUS_MAX_LEN);
sub_peer = brcm_subchannel_get_peer(sub);
if (!line_config[p->line_id].enabled) {
ast_debug(1, "tel_line %d disabled!\n", p->line_id);
@@ -897,6 +907,12 @@ static int brcm_hangup(struct ast_channel *ast)
}
pvt_lock(sub->parent, "TELCHAN hangup");
p = sub->parent;
+
+ if (!strcasecmp(p->callStatus, "Connected") || !strcasecmp(p->callStatus, "Dialing"))
+ strncpy(p->callStatus, "Disconnected", CALL_STATUS_MAX_LEN);
+ else
+ strncpy(p->callStatus, "Idle", CALL_STATUS_MAX_LEN);
+
sub_peer = brcm_subchannel_get_peer(sub);
ast_debug(1, "brcm_hangup(%s) line_id=%d connection_id=%d dialtone=%s channel_state=%s\n",
ast_channel_name(ast), p->line_id, sub->connection_id, dialtone_map[p->dialtone].str,
@@ -1023,6 +1039,7 @@ static int brcm_answer(struct ast_channel *ast)
ast_debug(1, "brcm_answer(%s)\n", ast_channel_name(ast));
pvt_lock(pvt, "TELCHAN answer");
+ strncpy(pvt->callStatus, "Connected", CALL_STATUS_MAX_LEN);
/* For attended call transfer, if the transfer target has accepted the call initiated by
* us as the tranferee, we can terminate the original call with the transferor */
@@ -1672,6 +1689,7 @@ static int handle_dialtone_timeout(const void *data)
struct brcm_pvt *p = (struct brcm_pvt *) data;
pvt_lock(p, "dialtone timeout");
+ strncpy(p->callStatus, "Disconnected", CALL_STATUS_MAX_LEN);
//ast_mutex_lock(&p->lock);
p->dialtone_timeout_timer_id = -1;
@@ -2394,6 +2412,10 @@ static void *brcm_process_event(struct endpt_event *ev)
switch (ev->event) {
case EVENT_OFFHOOK: {
ast_debug(9, "EVENT_OFFHOOK detected\n");
+ if (!strlen(p->callStatus) || !strcasecmp(p->callStatus, "Idle"))
+ strncpy(p->callStatus, "Dialing", CALL_STATUS_MAX_LEN);
+ else if (!strcasecmp(p->callStatus, "Alerting"))
+ strncpy(p->callStatus, "Connected", CALL_STATUS_MAX_LEN);
/* Reset the dtmf buffer */
memset(p->dtmfbuf, 0, sizeof(p->dtmfbuf));
@@ -2456,6 +2478,7 @@ static void *brcm_process_event(struct endpt_event *ev)
}
case EVENT_ONHOOK: {
ast_debug(9, "EVENT_ONHOOK detected\n");
+ strncpy(p->callStatus, "Idle", CALL_STATUS_MAX_LEN);
if (sub->channel_state == OFFHOOK || sub->channel_state == AWAITONHOOK) {
/* Received EVENT_ONHOOK in state OFFHOOK/AWAITONHOOK, stop dial/congestion tone */
brcm_stop_dialtone(p);
@@ -3707,8 +3730,48 @@ static int asterisk_event(struct ubus_context *ctx, struct ubus_object *obj,
return UBUS_STATUS_OK;
}
+// Reception of RPC call
+// ubus call asterisk call_status '{ "line" : 1 }'
+static int asterisk_call_status(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__EVENT_MAX];
+ enum ubus_msg_status res = UBUS_STATUS_UNKNOWN_ERROR;
+ struct blob_buf blob;
+ int line;
+
+ blobmsg_parse(asterisk_call_status_policy, __CALL_STATUS_MAX,
+ tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[CALL_STATUS_LINE_ID] )
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ memset(&blob, 0, sizeof(blob));
+ if(blob_buf_init(&blob, 0))
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ line = blobmsg_get_u32(tb[CALL_STATUS_LINE_ID]);
+
+ struct brcm_pvt *p = iflist;
+ while(p) {
+ if (line == p->line_id) {
+ blobmsg_add_u32(&blob, "line", p->line_id);
+ blobmsg_add_string(&blob, "call_status", strlen(p->callStatus) ? p->callStatus : "Idle");
+ res = UBUS_STATUS_OK;
+ break;
+ }
+ p = brcm_get_next_pvt(p);
+ }
+
+ ubus_send_reply(ctx, req, blob.head);
+ blob_buf_free(&blob);
+ return res;
+}
+
static struct ubus_method asterisk_methods[] = {
UBUS_METHOD("event", asterisk_event, asterisk_event_policy),
+ UBUS_METHOD("call_status", asterisk_call_status, asterisk_call_status_policy),
};
static struct ubus_object_type asterisk_obj_type = UBUS_OBJECT_TYPE("asterisk", asterisk_methods);
diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h
index 33a7da3..375d1dd 100644
--- a/channels/chan_brcm.h
+++ b/channels/chan_brcm.h
@@ -10,6 +10,7 @@
#define DEFAULT_CALLER_ID "Unknown"
#define PHONE_MAX_BUF 480
+#define CALL_STATUS_MAX_LEN 14
#define TIMEMSEC 1000
@@ -145,6 +146,7 @@ struct brcm_pvt {
char language[MAX_LANGUAGE];
char cid_num[AST_MAX_EXTENSION];
char cid_name[AST_MAX_EXTENSION];
+ char callStatus[CALL_STATUS_MAX_LEN];
struct brcm_subchannel *sub[NUM_SUBCHANNELS]; /* List of sub-channels, needed for callwaiting and 3-way support */
int hf_detected; /* Hook flash detected */
--
GitLab