Code Sync up from tizen_2.4
[platform/core/telephony/tel-plugin-imc.git] / src / imc_ps.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Arun Shukla <arun.shukla@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include <glib.h>
27 #include <fcntl.h>
28 #include <sys/ioctl.h>
29
30 #include <tcore.h>
31 #include <hal.h>
32 #include <core_object.h>
33 #include <plugin.h>
34 #include <queue.h>
35 #include <co_ps.h>
36 #include <co_context.h>
37 #include <storage.h>
38 #include <server.h>
39 #include <at.h>
40 #include <util.h>
41 #include <type/ps.h>
42
43 #include "imc_common.h"
44 #include "imc_ps.h"
45
46 /*Invalid Session ID*/
47 #define PS_INVALID_CID  999 /*Need to check */
48
49 /*Maximum String length Of the Command*/
50 #define MAX_AT_CMD_STR_LEN  150
51
52 /*Command for PDP activation and Deactivation*/
53 #define AT_PDP_ACTIVATE 1
54 #define AT_PDP_DEACTIVATE 0
55
56 #define AT_XDNS_ENABLE 1
57 #define AT_XDNS_DISABLE 0
58 #define AT_SESSION_DOWN 0
59
60 enum ps_data_call_status {
61         PS_DATA_CALL_CTX_DEFINED,
62         PS_DATA_CALL_CONNECTED,
63         PS_DATA_CALL_NOT_CONNECTED = 3,
64 };
65
66 struct ps_user_data {
67         CoreObject *ps_context;
68         struct tnoti_ps_pdp_ipconfiguration data_call_conf;
69 };
70
71 static void  __convert_ipv4_atoi(unsigned char *ip4,  const char *str)
72 {
73         char *token = NULL;
74         char *temp = NULL;
75         char *ptr = NULL;
76         int local_index = 0;
77
78         temp = g_strdup(str);
79         token = strtok_r(temp, ".", &ptr);
80         while (token != NULL) {
81                 ip4[local_index++] = atoi(token);
82                 msg("   [%d]", ip4[local_index-1]);
83                 token = strtok_r(NULL, ".", &ptr);
84         }
85         g_free(temp);
86 }
87 static void _unable_to_get_pending(CoreObject *co_ps, CoreObject *ps_context)
88 {
89         struct tnoti_ps_call_status data_resp = {0};
90         dbg("Entry");
91
92         data_resp.context_id = tcore_context_get_id(ps_context);
93         data_resp.state = PS_DATA_CALL_NOT_CONNECTED;
94         dbg("Sending Call Status Notification - Context ID: [%d] Context State: [NOT CONNECTED]",
95                                         data_resp.context_id);
96
97         /* Send CALL Status Notification */
98         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)),
99                                 co_ps, TNOTI_PS_CALL_STATUS, sizeof(data_resp), &data_resp);
100
101         /* Set PS State to Deactivated */
102         (void) tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
103         dbg("Exit");
104 }
105
106 /*
107  * Notification - GPRS event reporting
108  *
109  * Notification -
110  * +CGEV: NW DEACT <PDP_type>, <PDP_addr>, [<cid>]
111  * The network has forced a context deactivation. The <cid> that was used to activate the context is provided if
112  * known to the MT
113  */
114 static gboolean on_cgev_notification(CoreObject *co_ps,
115         const void *data, void *user_data)
116 {
117         GSList *tokens = NULL;
118         GSList *lines = (GSList *)data;
119         const gchar *line = lines->data;
120         gchar *noti_data;
121         guint context_id;
122         TcoreHal *hal;
123         struct tnoti_ps_call_status noti = {0};
124         Server *server;
125
126         dbg("Entry");
127
128         if (line == NULL) {
129                 err("Ignore, No data present in notification received for CGEV");
130                 return TRUE;
131         }
132
133         dbg("Lines->data :%s", line);
134
135         tokens = tcore_at_tok_new(line);
136         if (g_slist_length(tokens) != 3) {
137                 err("Ignore, sufficient data not present for deactivation");
138                 goto out;
139
140         }
141         noti_data = g_slist_nth_data(tokens, 0);
142
143         /* Only care about NW context deactivation */
144         if (g_str_has_prefix(noti_data, "NW DEACT") == FALSE) {
145                 err("Ignore, only care about nw deactivation");
146                 goto out;
147         }
148
149         noti_data = g_slist_nth_data(tokens, 1);
150         dbg("PDP Address: %s", noti_data);
151
152         noti_data = g_slist_nth_data(tokens, 2);
153         /*TODO: Need to handle context id with multiple PDP*/
154         if (noti_data != NULL)
155                 context_id = (guint)atoi(noti_data);
156         else{
157                 err("No Context ID!");
158                 goto out;
159         }
160
161         dbg("Context %d deactivated", context_id);
162
163         /* Set State - CONNECTED */
164         noti.context_id = context_id;
165         noti.state = PS_DATA_CALL_NOT_CONNECTED;
166         dbg("Sending Call Status Notification - Context ID: [%d] Context State: [ NOT CONNECTED]", noti.context_id);
167
168         /* Send Notification */
169         server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
170         tcore_server_send_notification(server, co_ps,
171                                         TNOTI_PS_CALL_STATUS,
172                                         sizeof(struct tnoti_ps_call_status),
173                                         &noti);
174
175         hal = tcore_object_get_hal(co_ps);
176         if (tcore_hal_setup_netif(hal, co_ps, NULL, NULL, context_id,
177                                         FALSE) != TCORE_RETURN_SUCCESS)
178                 err("Failed to disable network interface");
179
180 out:
181
182         tcore_at_tok_free(tokens);
183         return TRUE;
184 }
185
186 static gboolean on_event_dun_call_notification(CoreObject *o, const void *data, void *user_data)
187 {
188         GSList *tokens = NULL;
189         const char *line = NULL;
190         int value = 0;
191         GSList *lines = NULL;
192         dbg("Entry");
193
194         lines = (GSList *) data;
195         if (g_slist_length(lines) != 1) {
196                 dbg("Unsolicited message BUT multiple lines");
197                 goto OUT;
198         }
199
200         line = (char *) (lines->data);
201         tokens = tcore_at_tok_new(line);
202         value = atoi(g_slist_nth_data(tokens, 0));
203
204         /*
205          * <status> may be
206          *      0: DUN Activation in progress
207          *      1: DUN Deactivation in progress
208          *      2: DUN Activated
209          *      3: DUN Deactivated
210          */
211         switch (value) {
212         case 0:    /* FALL THROUGH */
213         case 1:
214         {
215                 break;
216         }
217
218         case 2:
219         {
220                 /* TODO:- Fill Data structure: 'data' */
221                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
222                                                                            TNOTI_PS_EXTERNAL_CALL, sizeof(struct tnoti_ps_external_call), &data);
223         }
224
225         case 3:
226         {
227                 /* TODO:- Fill Data structure: 'data' */
228                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
229                                                                            TNOTI_PS_EXTERNAL_CALL, sizeof(struct tnoti_ps_external_call), &data);
230         }
231         break;
232
233         default:
234                 break;
235         }
236
237 OUT:
238         /* Free tokens */
239         tcore_at_tok_free(tokens);
240
241         return TRUE;
242 }
243 static void on_response_undefine_context_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
244 {
245         CoreObject *co_ps = NULL;
246         const TcoreATResponse *resp = data;
247         CoreObject *ps_context = user_data;
248         dbg("Entry");
249
250         co_ps = tcore_pending_ref_core_object(p);
251         if (resp->success) {
252                 dbg("Response Ok");
253                 goto exit;
254         }
255         dbg("Response NOk");
256
257 exit:
258         _unable_to_get_pending(co_ps, ps_context);
259         return;
260 }
261
262 static void send_undefine_context_cmd(CoreObject *co_ps, CoreObject *ps_context)
263 {
264         TcoreHal *hal = NULL;
265         TcorePending *pending = NULL;
266         char cmd_str[MAX_AT_CMD_STR_LEN];
267         int cid = 0;
268
269         dbg("Entry");
270         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
271
272         /* FIXME: Before MUX setup, use PHY HAL directly. */
273         hal = tcore_object_get_hal(co_ps);
274
275         /*Getting Context ID from Core Object*/
276         cid = tcore_context_get_id(ps_context);
277
278         (void) sprintf(cmd_str, "AT+CGDCONT=%d", cid);
279         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
280
281         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
282                                                                    on_response_undefine_context_cmd, ps_context);
283         if (NULL == pending) {
284                 err("Unable to get the create a AT request ");
285                 goto error;
286         }
287         tcore_hal_send_request(hal, pending);
288         dbg("Exit: Successfully");
289         return;
290 error:
291         {
292                 dbg("Exit: With error");
293                 _unable_to_get_pending(co_ps, ps_context);
294                 return;
295         }
296 }
297
298 static void on_setup_pdp(CoreObject *co_ps, int result,
299                         const char *netif_name, void *user_data)
300 {
301         struct ps_user_data *ps_data = user_data;
302         struct tnoti_ps_call_status data_status = {0};
303         Server *server;
304
305         dbg("Entry");
306
307         if (!ps_data ) {
308                 err("PS_data unavailable. Exiting.");
309                 return;
310         }
311
312         if (result < 0) {
313                 /* Deactivate PDP context */
314                 tcore_ps_deactivate_context(co_ps, ps_data->ps_context, NULL);
315                 return;
316         }
317
318         dbg("Device name: [%s]", netif_name);
319         if (tcore_util_netif_up(netif_name) != TCORE_RETURN_SUCCESS) {
320                 err("util_netif_up() failed. errno=%d", errno);
321                 /* Deactivate PDP context */
322                 tcore_ps_deactivate_context(co_ps, ps_data->ps_context, NULL);
323                 return;
324         } else {
325                 dbg("tcore_util_netif_up() PASS...");
326         }
327
328         /* Set Device name */
329         //tcore_context_set_ipv4_devname(ps_context, netif_name);
330         g_strlcpy(ps_data->data_call_conf.devname, netif_name, sizeof(ps_data->data_call_conf.devname));
331
332         ps_data->data_call_conf.context_id = (int)tcore_context_get_id(ps_data->ps_context);
333
334         dbg("Sending IP Configuration Notification - Context ID: [%d] Context State: [CONNECTED]", ps_data->data_call_conf.context_id);
335         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)),
336                                         co_ps,
337                                         TNOTI_PS_PDP_IPCONFIGURATION,
338                                         sizeof(struct tnoti_ps_pdp_ipconfiguration),
339                                         &ps_data->data_call_conf);
340
341         /* Set State - CONNECTED */
342         data_status.context_id = tcore_context_get_id(ps_data->ps_context);
343         data_status.state = PS_DATA_CALL_CONNECTED;
344         dbg("Sending Call Status Notification - Context ID: [%d] Context State: [CONNECTED]", data_status.context_id);
345
346         /* Send Notification */
347         server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
348         tcore_server_send_notification(server, co_ps,
349                                         TNOTI_PS_CALL_STATUS,
350                                         sizeof(struct tnoti_ps_call_status),
351                                         &data_status);
352
353         g_free(ps_data);
354         dbg("Exit");
355 }
356
357 static void on_response_get_dns_cmnd(TcorePending *p, int data_len, const void *data, void *user_data)
358 {
359         GSList *tokens = NULL;
360         GSList *pRespData;
361         const char *line = NULL;
362         char *dns_prim = NULL;
363         char *dns_sec = NULL;
364         char *token_dns = NULL;
365         int no_pdp_active = 0;
366         struct ps_user_data *ps_data = user_data;
367         const TcoreATResponse *resp = data;
368         CoreObject *co_ps = tcore_pending_ref_core_object(p);
369         int cid = tcore_context_get_id(ps_data->ps_context);
370         TcoreHal *h = tcore_object_get_hal(co_ps);
371
372         dbg("Entry");
373
374         if (resp->final_response) {
375                 dbg("Response OK");
376                 if (resp->lines) {
377                         dbg("DNS data present in the Response");
378                         pRespData = (GSList *) resp->lines;
379                         no_pdp_active = g_slist_length(pRespData);
380                         dbg("Total Number of Active PS Context: [%d]", no_pdp_active);
381                         if (0 == no_pdp_active) {
382                                 goto exit_fail;
383                         }
384
385                         while (pRespData) {
386                                 line = (const char *) pRespData->data;
387                                 dbg("Received Data: [%s]", line);
388                                 tokens = tcore_at_tok_new(line);
389
390                                 /* Check if Context ID is matching */
391                                 if (cid == atoi(g_slist_nth_data(tokens, 0))) {
392                                         dbg("Found the DNS details for the Current Context - Context ID: [%d]", cid);
393                                         break;
394                                 }
395
396                                 /* Free tokens */
397                                 tcore_at_tok_free(tokens);
398                                 tokens = NULL;
399
400                                 /* Move to next line */
401                                 pRespData = pRespData->next;
402                         }
403
404                         /* Read primary DNS */
405                         {
406                                 token_dns = g_slist_nth_data(tokens, 1);
407
408                                 /* Strip off starting " and ending " from this token to read actual PDP address */
409                                 dns_prim = util_removeQuotes((void *)token_dns);
410                                 dbg("Primary DNS: [%s]", dns_prim);
411                         }
412
413                         /* Read Secondary DNS */
414                         {
415                                 token_dns = g_slist_nth_data(tokens, 2);
416
417                                 /* Strip off starting " and ending " from this token to read actual PDP address */
418                                 dns_sec = util_removeQuotes((void *)token_dns);
419                                 dbg("Secondary DNS: [%s]", dns_sec);
420                         }
421
422                         if ((g_strcmp0("0.0.0.0", dns_prim) == 0)
423                                         && (g_strcmp0("0.0.0.0", dns_sec) == 0)) {
424                                 dbg("Invalid DNS");
425
426                                 g_free(dns_prim);
427                                 g_free(dns_sec);
428
429                                 tcore_at_tok_free(tokens);
430                                 tokens = NULL;
431
432                                 goto exit_fail;
433                         }
434
435                         __convert_ipv4_atoi(ps_data->data_call_conf.primary_dns,  dns_prim);
436                         __convert_ipv4_atoi(ps_data->data_call_conf.secondary_dns,  dns_sec);
437
438                         util_hex_dump("   ", 4, ps_data->data_call_conf.primary_dns);
439                         util_hex_dump("   ", 4, ps_data->data_call_conf.secondary_dns);
440
441                         /* Set DNS Address */
442                         tcore_context_set_dns1(ps_data->ps_context, dns_prim);
443                         tcore_context_set_dns2(ps_data->ps_context, dns_sec);
444
445                         g_free(dns_prim);
446                         g_free(dns_sec);
447
448                         tcore_at_tok_free(tokens);
449                         tokens = NULL;
450                         goto exit_success;
451                 } else {
452                         dbg("No data present in the Response");
453                 }
454         }
455         dbg("Response NOK");
456
457 exit_fail:
458         dbg("Adding default DNS");
459
460         __convert_ipv4_atoi(ps_data->data_call_conf.primary_dns, "8.8.8.8");
461         __convert_ipv4_atoi(ps_data->data_call_conf.secondary_dns, "8.8.4.4");
462
463         tcore_context_set_dns1(ps_data->ps_context, (const char *)ps_data->data_call_conf.primary_dns);
464         tcore_context_set_dns2(ps_data->ps_context, (const char *)ps_data->data_call_conf.secondary_dns);
465
466 exit_success:
467         /* Mount network interface */
468         if (tcore_hal_setup_netif(h, co_ps, on_setup_pdp, (void *)ps_data, cid, TRUE)
469                         != TCORE_RETURN_SUCCESS) {
470                 err("Setup network interface failed");
471                 return;
472         }
473
474         dbg("EXIT : Without error");
475 }
476
477 static TReturn send_get_dns_cmd(CoreObject *co_ps, struct ps_user_data *ps_data)
478 {
479         TcoreHal *hal = NULL;
480         TcorePending *pending = NULL;
481         char cmd_str[MAX_AT_CMD_STR_LEN];
482
483         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
484
485         dbg("Entry");
486         hal = tcore_object_get_hal(co_ps);
487
488         (void) sprintf(cmd_str, "AT+XDNS?");
489         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
490
491         pending = tcore_at_pending_new(co_ps, cmd_str, "+XDNS", TCORE_AT_MULTILINE,
492                                                                    on_response_get_dns_cmnd, (void *)ps_data);
493         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
494                 return TCORE_RETURN_SUCCESS;
495         }
496         _unable_to_get_pending(co_ps, ps_data->ps_context);
497         return TCORE_RETURN_FAILURE;
498 }
499
500 static void on_response_get_pdp_address(TcorePending *p, int data_len, const void *data, void *user_data)
501 {
502         const TcoreATResponse *resp = data;
503         CoreObject *co_ps = tcore_pending_ref_core_object(p);
504         GSList *tokens = NULL;
505         const char *line;
506         char *token_pdp_address = NULL;
507         char *token_address = NULL;
508         CoreObject *ps_context = user_data;
509         struct ps_user_data *ps_data = {0, };
510
511         dbg("Enetered");
512
513         if (resp->final_response) {
514                 ps_data = g_try_malloc0(sizeof (struct ps_user_data));
515                 ps_data->ps_context = ps_context;
516                 dbg("RESPONSE OK");
517                 if (resp->lines != NULL) {
518                         line = (const char *) resp->lines->data;
519                         tokens = tcore_at_tok_new(line);
520                         if (g_slist_length(tokens) < 2) {
521                                 msg("Invalid message");
522                                 goto error;
523                         }
524                         dbg("Received Data: [%s]", line);
525
526                         /* CID is already stored in ps_context, skip over & read PDP address */
527                         token_address = g_slist_nth_data(tokens, 1);
528                         token_pdp_address = util_removeQuotes((void *)token_address);
529                         dbg("IP Address: [%s]", token_pdp_address);
530
531                         __convert_ipv4_atoi(ps_data->data_call_conf.ip_address,  token_pdp_address);
532
533                         util_hex_dump("   ", 4, ps_data->data_call_conf.ip_address);
534
535                         /* Strip off starting " and ending " from this token to read actual PDP address */
536                         /* Set IP Address */
537                         (void)tcore_context_set_address(ps_context, (const char *)ps_data->data_call_conf.ip_address);
538
539                         g_free(token_pdp_address);
540                 }
541
542                 /* Get DNS Address */
543                 (void) send_get_dns_cmd(co_ps, ps_data);
544         } else {
545                 dbg("Response NOK");
546
547                 /*without PDP address we will not be able to start packet service*/
548                 tcore_ps_deactivate_context(co_ps, ps_context, NULL);
549         }
550 error:
551         tcore_at_tok_free(tokens);
552         return;
553 }
554
555 static TReturn send_get_pdp_address_cmd(CoreObject *co_ps, CoreObject *ps_context)
556 {
557         TcoreHal *hal = NULL;
558         TcorePending *pending = NULL;
559         unsigned int cid = PS_INVALID_CID;
560         char cmd_str[MAX_AT_CMD_STR_LEN] = {0};
561
562         dbg("Entry");
563         hal = tcore_object_get_hal(co_ps);
564
565         cid = tcore_context_get_id(ps_context);
566         (void) sprintf(cmd_str, "AT+CGPADDR=%d", cid);
567         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
568
569         pending = tcore_at_pending_new(co_ps, cmd_str, "+CGPADDR", TCORE_AT_SINGLELINE,
570                                                                    on_response_get_pdp_address, ps_context);
571         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
572                 return TCORE_RETURN_SUCCESS;
573         }
574         _unable_to_get_pending(co_ps, ps_context);
575         return TCORE_RETURN_FAILURE;
576 }
577
578 static void on_response_send_pdp_activate_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
579 {
580         CoreObject *co_ps = NULL;
581         const TcoreATResponse *resp = data;
582         CoreObject *ps_context = user_data;
583
584         int cid;
585         cid = tcore_context_get_id(ps_context);
586
587
588         dbg("Entry");
589         if (!p) {
590                 goto error;
591         }
592         co_ps = tcore_pending_ref_core_object(p);
593
594         if (resp->success) {
595                 dbg("Response OK");
596
597                 /* Getting the IP address and DNS from the modem */
598                 dbg("Getting IP Address");
599                 (void) send_get_pdp_address_cmd(co_ps, ps_context);
600                 return;
601         } else {
602                 dbg("Unable to activate PDP context - Context ID: [%d]", cid);
603                 dbg("Undefining PDP context");
604                 (void) tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
605                 send_undefine_context_cmd(co_ps, ps_context);
606                 return;
607         }
608 error:
609         {
610                 _unable_to_get_pending(co_ps, ps_context);
611                 return;
612         }
613 }
614
615 static TReturn send_pdp_activate_cmd(CoreObject *co_ps, CoreObject *ps_context)
616 {
617         TcoreHal *hal = NULL;
618         TcorePending *pending = NULL;
619         char cmd_str[MAX_AT_CMD_STR_LEN] = {0};
620         int cid = 0;
621         dbg("Entry");
622         /* FIXME: Before MUX setup, use PHY HAL directly. */
623         hal = tcore_object_get_hal(co_ps);
624
625         /*Getting Context ID from Core Object*/
626         cid = tcore_context_get_id(ps_context);
627         (void) sprintf(cmd_str, "AT+CGACT=%d,%d", AT_PDP_ACTIVATE, cid);
628         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
629
630         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
631                                                                    on_response_send_pdp_activate_cmd, ps_context);
632         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
633                 return TCORE_RETURN_SUCCESS;
634         }
635         _unable_to_get_pending(co_ps, ps_context);
636         return TCORE_RETURN_FAILURE;
637 }
638
639 static TReturn activate_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
640 {
641         dbg("Entry");
642         return send_pdp_activate_cmd(co_ps, ps_context);
643 }
644
645 static void on_response_send_pdp_deactivate_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
646 {
647         CoreObject *co_ps = NULL;
648         const TcoreATResponse *resp = data;
649         CoreObject *ps_context = user_data;
650         TcoreHal *hal = NULL;
651         unsigned char context_id = 0;
652
653         dbg("Entry");
654         if (resp->success) {
655                 dbg("Response Ok");
656                 if (!p) {
657                         err("Invalid pending data");
658                         goto OUT;
659                 }
660                 co_ps = tcore_pending_ref_core_object(p);
661                 hal = tcore_object_get_hal(co_ps);
662                 context_id = tcore_context_get_id(ps_context);
663                 dbg("Context ID : %d", context_id);
664                 goto OUT;
665         } else {
666                 /* Since PDP deactivation failed, no need to move to
667                  * PS_DATA_CALL_NOT_CONNECTED state
668                  */
669                 err("Response NOk");
670                 return;
671         }
672 OUT:
673         _unable_to_get_pending(co_ps, ps_context);
674
675         if (tcore_hal_setup_netif(hal, co_ps, NULL, NULL, context_id, FALSE) != TCORE_RETURN_SUCCESS)
676                 err("Failed to disable network interface");
677 }
678
679 static TReturn send_pdp_deactivate_cmd(CoreObject *co_ps, CoreObject *ps_context)
680 {
681         TcoreHal *hal = NULL;
682         TcorePending *pending = NULL;
683         char cmd_str[MAX_AT_CMD_STR_LEN];
684         int cid = 0;
685
686         dbg("Entry");
687         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
688
689         hal = tcore_object_get_hal(co_ps);
690
691         /*Getting Context ID from Core Object*/
692         cid = tcore_context_get_id(ps_context);
693
694         (void) sprintf(cmd_str, "AT+CGACT=%d,%u", AT_PDP_DEACTIVATE, cid);
695         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
696
697         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
698                                                                    on_response_send_pdp_deactivate_cmd, ps_context);
699         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
700                 return TCORE_RETURN_SUCCESS;
701         }
702         return TCORE_RETURN_FAILURE;
703 }
704
705 static TReturn deactivate_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
706 {
707         dbg("Entry");
708         return send_pdp_deactivate_cmd(co_ps, ps_context);
709 }
710 static void on_response_xdns_enable_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
711 {
712         TcoreATResponse *resp = (TcoreATResponse *) data;
713         CoreObject *co_ps = tcore_pending_ref_core_object(p);
714         CoreObject *ps_context = user_data;
715         struct tnoti_ps_call_status noti = {0};
716         int cid = -1;
717
718         dbg("Entry");
719
720         cid = tcore_context_get_id(ps_context);
721
722         if (resp->success) {
723                 dbg("Response OK");
724                 dbg("DNS address getting is Enabled");
725                 noti.context_id = cid;
726                 noti.state = PS_DATA_CALL_CTX_DEFINED;
727         } else {
728                 dbg("Response NOK");
729                 noti.context_id = cid;
730                 noti.state = PS_DATA_CALL_NOT_CONNECTED;
731                 /*If response to enable the DNS NOK then we will use google DNS for the PDP context*/
732         }
733
734         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps,
735                                                                    TNOTI_PS_CALL_STATUS, sizeof(struct tnoti_ps_call_status), &noti);
736         return;
737 }
738
739 static TReturn send_xdns_enable_cmd(CoreObject *co_ps, CoreObject *ps_context)
740 {
741         TcoreHal *hal = NULL;
742         TcorePending *pending = NULL;
743         int cid = -1;
744         char cmd_str[MAX_AT_CMD_STR_LEN];
745
746         dbg("Entry");
747         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
748
749         hal = tcore_object_get_hal(co_ps);
750         cid = tcore_context_get_id(ps_context);
751
752         (void) sprintf(cmd_str, "AT+XDNS=%d,%d", cid, AT_XDNS_ENABLE);
753         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
754
755         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
756                                                                    on_response_xdns_enable_cmd, ps_context);
757         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
758                 return TCORE_RETURN_SUCCESS;
759         }
760         _unable_to_get_pending(co_ps, ps_context);
761         return TCORE_RETURN_FAILURE;
762 }
763
764 static void on_response_define_pdp_context(TcorePending *p, int data_len, const void *data, void *user_data)
765 {
766         const TcoreATResponse *resp = data;
767         CoreObject *ps_context = (CoreObject *) user_data;
768         CoreObject *co_ps = tcore_pending_ref_core_object(p);
769
770         dbg("Entry");
771         if (resp->success) {
772                 dbg("Response OK");
773                 send_xdns_enable_cmd(co_ps, ps_context);
774         } else {
775                 dbg("response NOK");
776                 _unable_to_get_pending(co_ps, ps_context);
777                 dbg("Exiting");
778         }
779         return;
780 }
781
782 static TReturn define_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
783 {
784         TcoreHal *hal = NULL;
785         TcorePending *pending = NULL;
786         char *apn = NULL;
787         char cmd_str[MAX_AT_CMD_STR_LEN] = {0};
788         char pdp_type_str[10] = {0};
789         unsigned int cid = PS_INVALID_CID;
790         enum co_context_type pdp_type;
791         enum co_context_d_comp d_comp;
792         enum co_context_h_comp h_comp;
793
794         dbg("Entry");
795
796         cid = tcore_context_get_id(ps_context);
797         pdp_type = tcore_context_get_type(ps_context);
798         d_comp = tcore_context_get_data_compression(ps_context);
799         h_comp = tcore_context_get_header_compression(ps_context);
800         apn = tcore_context_get_apn(ps_context);
801
802         hal = tcore_object_get_hal(co_ps);
803         switch (pdp_type) {
804         case CONTEXT_TYPE_X25:
805         {
806                 dbg("CONTEXT_TYPE_X25");
807                 strcpy(pdp_type_str, "X.25");
808                 break;
809         }
810
811         case CONTEXT_TYPE_IP:
812         {
813                 dbg("CONTEXT_TYPE_IP");
814                 strcpy(pdp_type_str, "IP");
815         }
816         break;
817
818         case CONTEXT_TYPE_PPP:
819         {
820                 dbg("CONTEXT_TYPE_PPP");
821                 strcpy(pdp_type_str, "PPP");
822         }
823         break;
824
825         case CONTEXT_TYPE_IPV6:
826         {
827                 dbg("CONTEXT_TYPE_IPV6");
828                 strcpy(pdp_type_str, "IPV6");
829                 break;
830         }
831
832         default:
833         {
834                 /*PDP Type not supported supported*/
835                 dbg("Unsupported PDP type: %d returning ", pdp_type);
836                 g_free(apn);
837                 return TCORE_RETURN_FAILURE;
838         }
839         }
840         dbg("Activating context for CID: %d", cid);
841         (void) sprintf(cmd_str, "AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d", cid, pdp_type_str, apn, d_comp, h_comp);
842         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
843         g_free(apn);
844
845         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
846                                                                    on_response_define_pdp_context, ps_context);
847         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
848                 return TCORE_RETURN_SUCCESS;
849         }
850         _unable_to_get_pending(co_ps, ps_context);
851         return TCORE_RETURN_FAILURE;
852 }
853
854 static struct tcore_ps_operations ps_ops = {
855         .define_context = define_ps_context,
856         .activate_context = activate_ps_context,
857         /* Use AT_standard entry point */
858         .deactivate_context = deactivate_ps_context,
859 };
860
861 gboolean imc_ps_init(TcorePlugin *cp, CoreObject *co_ps)
862 {
863         TcorePlugin *plugin = tcore_object_ref_plugin(co_ps);
864
865         dbg("Entry");
866
867         /* Set operations */
868         tcore_ps_set_ops(co_ps, &ps_ops);
869
870         tcore_object_add_callback(co_ps, "+CGEV", on_cgev_notification, NULL);
871         tcore_object_add_callback(co_ps, "+XNOTIFYDUNSTATUS", on_event_dun_call_notification, plugin);
872
873         dbg("Exit");
874
875         return TRUE;
876 }
877
878 void imc_ps_exit(TcorePlugin *cp, CoreObject *co_ps)
879 {
880         dbg("Exit");
881 }