at_ps: Implement activate_context
authorGuillaume Zajac <guillaume.zajac@linux.intel.com>
Wed, 19 Dec 2012 10:38:01 +0000 (11:38 +0100)
committerwootak.jung <wootak.jung@samsung.com>
Sun, 24 Mar 2013 06:48:51 +0000 (15:48 +0900)
Change-Id: I379140ca1a93511eaca19ae88a9c8f937d450f6c

src/at_ps.c

index 8a87384..2b5426a 100644 (file)
 #include <glib.h>
 
 #include <tcore.h>
-#include <hal.h>
-#include <core_object.h>
+#include <server.h>
 #include <plugin.h>
+#include <core_object.h>
+#include <hal.h>
+#include <at.h>
+#include <util.h>
+
 #include <co_ps.h>
+#include <co_context.h>
 
 #include "at_ps.h"
 
+enum pdp_context_state {
+       DEACTIVATE      = 0,
+       ACTIVATE        = 1,
+};
+
+static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
+                                       enum pdp_context_state state);
+
+static void on_confirmation_ps_message_send(TcorePending *p, gboolean result,
+                                               void *user_data)
+{
+       dbg("msg out from queue");
+
+       dbg("Sending %s", (result == TRUE) ? "OK" : "FAIL");
+}
+
+static void notify_context_deactivated(CoreObject *co_ps,
+                                       CoreObject *ps_context)
+{
+       struct tnoti_ps_call_status data_resp = {0};
+       unsigned int cid = tcore_context_get_id(ps_context);
+       Server *server;
+
+       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));
+
+       tcore_server_send_notification(server, co_ps, TNOTI_PS_CALL_STATUS,
+                                       sizeof(struct tnoti_ps_call_status),
+                                       &data_resp);
+
+       dbg("Exit");
+}
+
+static void on_setup_netif(CoreObject *co_ps, const char *netif_name,
+                               void *user_data)
+{
+       CoreObject *ps_context = user_data;
+       struct tnoti_ps_call_status data_status = {0};
+       Server *server;
+
+       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);
+               return;
+       }
+
+       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;
+
+       tcore_server_send_notification(server, co_ps,
+                                       TNOTI_PS_CALL_STATUS,
+                                       sizeof(struct tnoti_ps_call_status),
+                                       &data_status);
+
+       dbg("Exit");
+}
+
+static void on_response_get_pdp_address(TcorePending *p, int data_len,
+                                       const void *data, void *user_data)
+{
+       CoreObject *co_ps = tcore_pending_ref_core_object(p);
+       CoreObject *ps_context = user_data;
+       TcoreHal *h = tcore_object_get_hal(co_ps);
+       GSList *tokens = NULL;
+       const TcoreATResponse *resp = data;
+       const char *line;
+       char *pdp_address;
+       char *real_pdp_address;
+       int cid = tcore_context_get_id(ps_context);
+
+       dbg("Enter");
+
+       if (NULL == resp->final_response) {
+               err("Response NOK");
+               goto error;
+       }
+
+       dbg("Response OK");
+
+       if (NULL == resp->lines) {
+               err("Invalid response line");
+               goto error;
+       }
+
+       line = (const char *)resp->lines->data;
+       tokens = tcore_at_tok_new(line);
+       if (g_slist_length(tokens) < 2) {
+               err("Invalid message");
+               goto error;
+       }
+
+       dbg("Line: %s", line);
+
+       /* Skip CID & read directly IP address */
+       pdp_address = g_slist_nth_data(tokens, 1);
+       real_pdp_address = tcore_at_tok_extract(pdp_address);
+
+       tcore_context_set_ipv4_addr(ps_context, real_pdp_address);
+
+       dbg("PDP address: %s", real_pdp_address);
+
+       g_free(real_pdp_address);
+
+       dbg("Adding default DNS");
+
+       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)
+               goto out;
+
+error:
+       err("Failed to get PDP address deactivating context...");
+       set_pdp_context(co_ps, ps_context, DEACTIVATE);
+
+out:
+       if (tokens != NULL)
+               tcore_at_tok_free(tokens);
+
+       dbg("Exit");
+}
+
+static void get_pdp_address(CoreObject *co_ps, CoreObject *ps_context)
+{
+       char *cmd_str = NULL;
+       unsigned int cid = tcore_context_get_id(ps_context);
+
+       dbg("Enter");
+
+       cmd_str = g_strdup_printf("AT+CGPADDR=%d", cid);
+
+       if (tcore_prepare_and_send_at_request(co_ps, cmd_str, NULL,
+                                       TCORE_AT_NO_RESULT, NULL,
+                                       on_response_get_pdp_address,
+                                       ps_context,
+                                       on_confirmation_ps_message_send, NULL)
+                                       != TCORE_RETURN_SUCCESS) {
+               err("Failed to prepare and send AT request");
+               set_pdp_context(co_ps, ps_context, DEACTIVATE);
+       }
+
+       g_free(cmd_str);
+
+       dbg("Exit");
+}
+
+static void on_response_set_pdp_context_activate(TcorePending *p, int data_len,
+                                                       const void *data,
+                                                       void *user_data)
+{
+       CoreObject *co_ps = tcore_pending_ref_core_object(p);
+       const TcoreATResponse *resp = data;
+       CoreObject *ps_context = user_data;
+
+       dbg("Enter");
+
+       if (resp->success) {
+               dbg("Response OK");
+               get_pdp_address(co_ps, ps_context);
+       } else {
+               /* TODO: Manage CME errors */
+               err("Response NOK");
+               notify_context_deactivated(co_ps, ps_context);
+       }
+
+       dbg("Exit");
+}
+
+static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
+                                       enum pdp_context_state state)
+{
+       char *cmd_str = NULL;
+       unsigned int cid = tcore_context_get_id(ps_context);
+       int ret = TCORE_RETURN_SUCCESS;
+       TcorePendingResponseCallback cb = NULL;
+       gboolean activate = (state == ACTIVATE);
+
+       dbg("Enter");
+
+       dbg("CID %d %s", cid, activate ? "activation" : "deactivation");
+
+       if (activate == TRUE)
+               cb = on_response_set_pdp_context_activate;
+       else
+               return TCORE_RETURN_ENOSYS;
+
+       cmd_str = g_strdup_printf("AT+CGACT=%d,%d", activate ? 1 : 0, cid);
+
+       if (tcore_prepare_and_send_at_request(co_ps, cmd_str, NULL,
+                                       TCORE_AT_NO_RESULT, NULL,
+                                       cb, 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);
+               ret =  TCORE_RETURN_FAILURE;
+       }
+
+       g_free(cmd_str);
+
+       dbg("Exit");
+
+       return ret;
+}
+
+static void on_response_define_pdp_context(TcorePending *p, int data_len,
+                                               const void *data,
+                                               void *user_data)
+{
+       const TcoreATResponse *resp = data;
+       CoreObject *ps_context = user_data;
+       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);
+       } else {
+               err("Response NOK");
+               notify_context_deactivated(co_ps, ps_context);
+       }
+
+       dbg("Exit");
+}
+
+static TReturn define_pdp_context(CoreObject *co_ps, CoreObject *ps_context)
+{
+       char *apn = NULL;
+       char *cmd_str = NULL;
+       char *pdp_type_str = NULL;
+       unsigned int cid;
+       enum co_context_type pdp_type;
+       enum co_context_d_comp d_comp;
+       enum co_context_h_comp h_comp;
+       int ret = TCORE_RETURN_FAILURE;
+
+       dbg("Enter");
+
+       pdp_type = tcore_context_get_type(ps_context);
+       cid = tcore_context_get_id(ps_context);
+
+       switch (pdp_type) {
+       case CONTEXT_TYPE_X25:
+               dbg("CONTEXT_TYPE_X25");
+               pdp_type_str = g_strdup("X.25");
+               break;
+
+       case CONTEXT_TYPE_IP:
+               dbg("CONTEXT_TYPE_IP");
+               pdp_type_str = g_strdup("IP");
+               break;
+
+       case CONTEXT_TYPE_PPP:
+               dbg("CONTEXT_TYPE_PPP");
+               pdp_type_str = g_strdup("PPP");
+               break;
+
+       case CONTEXT_TYPE_IPV6:
+               dbg("CONTEXT_TYPE_IPV6");
+               pdp_type_str = g_strdup("IPV6");
+               break;
+
+       default:
+               /* PDP Type not supported supported */
+               err("Unsupported PDP type %d ", pdp_type);
+
+               goto error;
+       }
+
+       d_comp = tcore_context_get_data_compression(ps_context);
+       h_comp = tcore_context_get_header_compression(ps_context);
+       apn = tcore_context_get_apn(ps_context);
+
+       cmd_str = g_strdup_printf("AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d", cid,
+                                       pdp_type_str, apn, d_comp, h_comp);
+
+       ret = tcore_prepare_and_send_at_request(co_ps, cmd_str, NULL,
+                                       TCORE_AT_NO_RESULT, NULL,
+                                       on_response_define_pdp_context,
+                                       ps_context,
+                                       on_confirmation_ps_message_send, NULL);
+
+       g_free(pdp_type_str);
+       g_free(cmd_str);
+       g_free(apn);
+
+       if (ret == TCORE_RETURN_SUCCESS)
+               goto out;
+
+       err("Failed to prepare and send AT request");
+
+error:
+       notify_context_deactivated(co_ps, ps_context);
+
+out:
+
+       dbg("Exit");
+
+       return ret;
+}
+
 static TReturn activate_ps_context(CoreObject *co_ps, CoreObject *ps_context,
                                        void *user_data)
 {
-       return TCORE_RETURN_SUCCESS;
+       return define_pdp_context(co_ps, ps_context);
 }
 
 static TReturn deactivate_ps_context(CoreObject *co_ps, CoreObject *ps_context,
                                        void *user_data)
 {
-       return TCORE_RETURN_SUCCESS;
+       return TCORE_RETURN_ENOSYS;
 }
 
 static struct tcore_ps_operations ps_ops = {