Generate Licence file
[platform/core/telephony/tel-plugin-at_standard.git] / src / at_ps.c
index 2b5426a..8268188 100644 (file)
@@ -29,7 +29,6 @@
 #include <core_object.h>
 #include <hal.h>
 #include <at.h>
-#include <util.h>
 
 #include <co_ps.h>
 #include <co_context.h>
@@ -52,20 +51,17 @@ static void on_confirmation_ps_message_send(TcorePending *p, gboolean result,
        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),
@@ -74,7 +70,48 @@ static void notify_context_deactivated(CoreObject *co_ps,
        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;
@@ -83,21 +120,20 @@ static void on_setup_netif(CoreObject *co_ps, const char *netif_name,
 
        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,
@@ -122,14 +158,14 @@ static void on_response_get_pdp_address(TcorePending *p, int data_len,
 
        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;
        }
@@ -157,8 +193,8 @@ static void on_response_get_pdp_address(TcorePending *p, int data_len,
 
        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:
@@ -166,15 +202,13 @@ 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");
@@ -210,9 +244,11 @@ static void on_response_set_pdp_context_activate(TcorePending *p, int data_len,
                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");
@@ -221,7 +257,7 @@ static void on_response_set_pdp_context_activate(TcorePending *p, int data_len,
 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;
@@ -234,7 +270,7 @@ static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
        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);
 
@@ -244,7 +280,7 @@ static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
                                        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;
        }
 
@@ -261,22 +297,24 @@ static void on_response_define_pdp_context(TcorePending *p, int data_len,
 {
        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;
@@ -343,50 +381,109 @@ static TReturn define_pdp_context(CoreObject *co_ps, CoreObject *ps_context)
        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);
 }