#include <core_object.h>
#include <hal.h>
#include <at.h>
-#include <util.h>
#include <co_ps.h>
#include <co_context.h>
dbg("Sending %s", (result == TRUE) ? "OK" : "FAIL");
}
-static void notify_context_deactivated(CoreObject *co_ps,
- CoreObject *ps_context)
+static void notify_context_status_changed(CoreObject *co_ps, unsigned int cid,
+ enum ps_data_call_status status)
{
struct tnoti_ps_call_status data_resp = {0};
- unsigned int cid = tcore_context_get_id(ps_context);
- Server *server;
+ TcorePlugin *p = tcore_object_ref_plugin(co_ps);
+ Server *server = tcore_plugin_ref_server(p);
dbg("Enter");
data_resp.context_id = cid;
- data_resp.state = TELEPHONY_GPRS_DATA_STATUS_NOCARRIER;
- data_resp.result = 0;
-
- server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
+ data_resp.state = status;
tcore_server_send_notification(server, co_ps, TNOTI_PS_CALL_STATUS,
sizeof(struct tnoti_ps_call_status),
dbg("Exit");
}
-static void on_setup_netif(CoreObject *co_ps, const char *netif_name,
+static void on_response_set_pdp_context_deactivate(TcorePending *p,
+ int data_len,
+ const void *data,
+ void *user_data)
+{
+ CoreObject *co_ps = tcore_pending_ref_core_object(p);
+ TcoreHal *h = tcore_object_get_hal(co_ps);
+ const TcoreATResponse *resp = data;
+ CoreObject *ps_context = user_data;
+ unsigned int cid = tcore_context_get_id(ps_context);
+
+ dbg("Enter");
+
+ /*
+ * AT+CGACT = 0 is returning NO CARRIER or an error. Just test if the
+ * response contains NO CARRIER else decode CME error.
+ */
+ if (resp->lines != NULL) {
+ const char *line;
+
+ line = (const char *)resp->lines->data;
+ if (g_strcmp0(line, "NO CARRIER") != 0) {
+ /* TODO: Decode CME error */
+ err("%s", line);
+ err("Context %d has not been deactivated", cid);
+
+ goto out;
+ }
+
+ }
+
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_NOT_CONNECTED);
+
+ if (tcore_hal_setup_netif(h, co_ps, NULL, NULL, cid,
+ FALSE) != TCORE_RETURN_SUCCESS)
+ err("Failed to disable network interface");
+
+out:
+ dbg("Exit");
+}
+
+static void on_setup_pdp(CoreObject *co_ps, int result, const char *netif_name,
void *user_data)
{
CoreObject *ps_context = user_data;
dbg("Enter");
- dbg("devname = [%s]", netif_name);
-
- if (tcore_util_netif_up(netif_name) != TCORE_RETURN_SUCCESS) {
- err("util_netif_up() failed.");
- set_pdp_context(co_ps, ps_context, DEACTIVATE);
+ if (result < 0) {
+ /* Deactivate PDP context */
+ tcore_ps_deactivate_context(co_ps, ps_context, NULL);
return;
}
+ dbg("devname = [%s]", netif_name);
+
tcore_context_set_ipv4_devname(ps_context, netif_name);
server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
data_status.context_id = tcore_context_get_id(ps_context);
- data_status.state = TELEPHONY_GPRS_DATA_STATUS_CONNECTED;
- data_status.result = 0;
+ data_status.state = PS_DATA_CALL_CONNECTED;
tcore_server_send_notification(server, co_ps,
TNOTI_PS_CALL_STATUS,
dbg("Enter");
- if (NULL == resp->final_response) {
+ if (resp->final_response == NULL) {
err("Response NOK");
goto error;
}
dbg("Response OK");
- if (NULL == resp->lines) {
+ if (resp->lines == NULL) {
err("Invalid response line");
goto error;
}
tcore_context_set_ipv4_dns(ps_context, "8.8.8.8", "8.8.4.4");
- if (tcore_hal_setup_netif(h, co_ps, on_setup_netif, ps_context, cid)
- == TCORE_RETURN_SUCCESS)
+ if (tcore_hal_setup_netif(h, co_ps, on_setup_pdp, ps_context, cid,
+ TRUE) == TCORE_RETURN_SUCCESS)
goto out;
error:
set_pdp_context(co_ps, ps_context, DEACTIVATE);
out:
- if (tokens != NULL)
- tcore_at_tok_free(tokens);
-
+ tcore_at_tok_free(tokens);
dbg("Exit");
}
static void get_pdp_address(CoreObject *co_ps, CoreObject *ps_context)
{
- char *cmd_str = NULL;
+ char *cmd_str;
unsigned int cid = tcore_context_get_id(ps_context);
dbg("Enter");
dbg("Response OK");
get_pdp_address(co_ps, ps_context);
} else {
+ unsigned int cid = tcore_context_get_id(ps_context);
+
/* TODO: Manage CME errors */
err("Response NOK");
- notify_context_deactivated(co_ps, ps_context);
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_NOT_CONNECTED);
}
dbg("Exit");
static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
enum pdp_context_state state)
{
- char *cmd_str = NULL;
+ char *cmd_str;
unsigned int cid = tcore_context_get_id(ps_context);
int ret = TCORE_RETURN_SUCCESS;
TcorePendingResponseCallback cb = NULL;
if (activate == TRUE)
cb = on_response_set_pdp_context_activate;
else
- return TCORE_RETURN_ENOSYS;
+ cb = on_response_set_pdp_context_deactivate;
cmd_str = g_strdup_printf("AT+CGACT=%d,%d", activate ? 1 : 0, cid);
on_confirmation_ps_message_send, NULL)
!= TCORE_RETURN_SUCCESS) {
err("Failed to prepare and send AT request");
- notify_context_deactivated(co_ps, ps_context);
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_NOT_CONNECTED);
ret = TCORE_RETURN_FAILURE;
}
{
const TcoreATResponse *resp = data;
CoreObject *ps_context = user_data;
+ unsigned int cid = tcore_context_get_id(ps_context);
CoreObject *co_ps = tcore_pending_ref_core_object(p);
dbg("Enter");
if (resp->success) {
dbg("Response OK");
- set_pdp_context(co_ps, ps_context, ACTIVATE);
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_CTX_DEFINED);
} else {
err("Response NOK");
- notify_context_deactivated(co_ps, ps_context);
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_NOT_CONNECTED);
}
dbg("Exit");
}
-static TReturn define_pdp_context(CoreObject *co_ps, CoreObject *ps_context)
+static TReturn define_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
+ void *user_data)
{
char *apn = NULL;
char *cmd_str = NULL;
err("Failed to prepare and send AT request");
error:
- notify_context_deactivated(co_ps, ps_context);
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_NOT_CONNECTED);
out:
-
dbg("Exit");
return ret;
}
+
+static gboolean on_cgev_notification(CoreObject *co_ps, const void *data,
+ void *user_data)
+{
+ GSList *tokens = NULL;
+ GSList *lines = (GSList *)data;
+ const char *line = lines->data;
+ char *noti_data;
+ unsigned int cid;
+ TcoreHal *hal;
+
+ dbg("Enter");
+
+ if (line == NULL)
+ goto out;
+
+ dbg("Lines->data :%s", line);
+
+ tokens = tcore_at_tok_new(line);
+ if (g_slist_length(tokens) != 3)
+ goto out;
+
+ noti_data = g_slist_nth_data(tokens, 0);
+
+ /* Only care about NW context deactivation */
+ if (g_str_has_prefix(noti_data, "NW DEACT") == FALSE)
+ goto out;
+
+ noti_data = g_slist_nth_data(tokens, 1);
+ dbg("PDP Address: %s", noti_data);
+
+ noti_data = g_slist_nth_data(tokens, 2);
+ cid = (unsigned int)atoi(noti_data);
+ dbg("Context %d deactivated", cid);
+
+ notify_context_status_changed(co_ps, cid, PS_DATA_CALL_NOT_CONNECTED);
+
+ hal = tcore_object_get_hal(co_ps);
+ if (tcore_hal_setup_netif(hal, co_ps, NULL, NULL, cid,
+ FALSE) != TCORE_RETURN_SUCCESS)
+ err("Failed to disable network interface");
+
+out:
+ tcore_at_tok_free(tokens);
+
+ dbg("Exit");
+
+ return TRUE;
+}
+
static TReturn activate_ps_context(CoreObject *co_ps, CoreObject *ps_context,
void *user_data)
{
- return define_pdp_context(co_ps, ps_context);
+ return set_pdp_context(co_ps, ps_context, ACTIVATE);
}
static TReturn deactivate_ps_context(CoreObject *co_ps, CoreObject *ps_context,
void *user_data)
{
- return TCORE_RETURN_ENOSYS;
+ return set_pdp_context(co_ps, ps_context, DEACTIVATE);
}
static struct tcore_ps_operations ps_ops = {
+ .define_context = define_pdp_context,
.activate_context = activate_ps_context,
.deactivate_context = deactivate_ps_context
};
-gboolean at_ps_init(TcorePlugin *p)
+gboolean at_ps_init(TcorePlugin *cp)
{
- CoreObject *co_ps;
+ CoreObject *co = NULL;
+ Server *server;
- co_ps = tcore_ps_new(p, "umts_ps", &ps_ops, NULL);
- if (NULL == co_ps)
+ co = tcore_ps_new(cp, &ps_ops, NULL);
+ if (co == NULL)
return FALSE;
+ tcore_object_add_callback(co, "+CGEV", on_cgev_notification, NULL);
+
+ server = tcore_plugin_ref_server(cp);
+ tcore_server_add_template_object(server, co);
+
return TRUE;
}
-void at_ps_exit(TcorePlugin *p)
+void at_ps_exit(TcorePlugin *cp)
{
- CoreObject *co_ps;
+ CoreObject *co;
+
+ if (cp == NULL)
+ return;
- co_ps = tcore_plugin_ref_core_object(p, "umts_ps");
- if (NULL == co_ps)
+ co = tcore_plugin_ref_core_object(cp, CORE_OBJECT_TYPE_PS);
+ if (co == NULL)
return;
- tcore_ps_free(co_ps);
+ tcore_object_free(co);
}