Apply secure-storage data migration
[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         break;
225
226         case 3:
227         {
228                 /* TODO:- Fill Data structure: 'data' */
229                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
230                                                                            TNOTI_PS_EXTERNAL_CALL, sizeof(struct tnoti_ps_external_call), &data);
231         }
232         break;
233
234         default:
235                 break;
236         }
237
238 OUT:
239         /* Free tokens */
240         tcore_at_tok_free(tokens);
241
242         return TRUE;
243 }
244 static void on_response_undefine_context_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
245 {
246         CoreObject *co_ps = NULL;
247         const TcoreATResponse *resp = data;
248         CoreObject *ps_context = user_data;
249         dbg("Entry");
250
251         co_ps = tcore_pending_ref_core_object(p);
252         if (resp->success) {
253                 dbg("Response Ok");
254                 goto exit;
255         }
256         dbg("Response NOk");
257
258 exit:
259         _unable_to_get_pending(co_ps, ps_context);
260         return;
261 }
262
263 static void send_undefine_context_cmd(CoreObject *co_ps, CoreObject *ps_context)
264 {
265         TcoreHal *hal = NULL;
266         TcorePending *pending = NULL;
267         char *cmd_str = NULL;
268         int cid = 0;
269
270         dbg("Entry");
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         cmd_str = g_strdup_printf("AT+CGDCONT=%d", cid);
279
280         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
281
282         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
283                                                                    on_response_undefine_context_cmd, ps_context);
284         if (NULL == pending) {
285                 err("Unable to get the create a AT request ");
286                 goto error;
287         }
288         tcore_hal_send_request(hal, pending);
289         g_free(cmd_str);
290         dbg("Exit: Successfully");
291         return;
292 error:
293         {
294                 dbg("Exit: With error");
295                 _unable_to_get_pending(co_ps, ps_context);
296                 g_free(cmd_str);
297                 return;
298         }
299 }
300
301 static void on_setup_pdp(CoreObject *co_ps, int result,
302                         const char *netif_name, void *user_data)
303 {
304         struct ps_user_data *ps_data = user_data;
305         struct tnoti_ps_call_status data_status = {0};
306         Server *server;
307
308         dbg("Entry");
309
310         if (!ps_data) {
311                 err("PS_data unavailable. Exiting.");
312                 return;
313         }
314
315         if (result < 0) {
316                 /* Deactivate PDP context */
317                 tcore_ps_deactivate_context(co_ps, ps_data->ps_context, NULL);
318                 return;
319         }
320
321         dbg("Device name: [%s]", netif_name);
322         if (tcore_util_netif_up(netif_name) != TCORE_RETURN_SUCCESS) {
323                 err("util_netif_up() failed. errno=%d", errno);
324                 /* Deactivate PDP context */
325                 tcore_ps_deactivate_context(co_ps, ps_data->ps_context, NULL);
326                 return;
327         } else {
328                 dbg("tcore_util_netif_up() PASS...");
329         }
330
331         /* Set Device name */
332         g_strlcpy(ps_data->data_call_conf.devname, netif_name, sizeof(ps_data->data_call_conf.devname));
333
334         ps_data->data_call_conf.context_id = (int)tcore_context_get_id(ps_data->ps_context);
335
336         dbg("Sending IP Configuration Notification - Context ID: [%d] Context State: [CONNECTED]", ps_data->data_call_conf.context_id);
337         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)),
338                                         co_ps,
339                                         TNOTI_PS_PDP_IPCONFIGURATION,
340                                         sizeof(struct tnoti_ps_pdp_ipconfiguration),
341                                         &ps_data->data_call_conf);
342
343         /* Set State - CONNECTED */
344         data_status.context_id = tcore_context_get_id(ps_data->ps_context);
345         data_status.state = PS_DATA_CALL_CONNECTED;
346         dbg("Sending Call Status Notification - Context ID: [%d] Context State: [CONNECTED]", data_status.context_id);
347
348         /* Send Notification */
349         server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
350         tcore_server_send_notification(server, co_ps,
351                                         TNOTI_PS_CALL_STATUS,
352                                         sizeof(struct tnoti_ps_call_status),
353                                         &data_status);
354
355         g_free(ps_data);
356         dbg("Exit");
357 }
358
359 static void on_response_get_dns_cmnd(TcorePending *p, int data_len, const void *data, void *user_data)
360 {
361         GSList *tokens = NULL;
362         GSList *pRespData;
363         const char *line = NULL;
364         char *dns_prim = NULL;
365         char *dns_sec = NULL;
366         char *token_dns = NULL;
367         int no_pdp_active = 0;
368         struct ps_user_data *ps_data = user_data;
369         const TcoreATResponse *resp = data;
370         CoreObject *co_ps = tcore_pending_ref_core_object(p);
371         int cid = tcore_context_get_id(ps_data->ps_context);
372         TcoreHal *h = tcore_object_get_hal(co_ps);
373
374         dbg("Entry");
375
376         if (resp->final_response) {
377                 dbg("Response OK");
378                 if (resp->lines) {
379                         dbg("DNS data present in the Response");
380                         pRespData = (GSList *) resp->lines;
381                         no_pdp_active = g_slist_length(pRespData);
382                         dbg("Total Number of Active PS Context: [%d]", no_pdp_active);
383                         if (0 == no_pdp_active)
384                                 goto exit_fail;
385
386                         while (pRespData) {
387                                 line = (const char *) pRespData->data;
388                                 dbg("Received Data: [%s]", line);
389                                 tokens = tcore_at_tok_new(line);
390
391                                 /* Check if Context ID is matching */
392                                 if (cid == atoi(g_slist_nth_data(tokens, 0))) {
393                                         dbg("Found the DNS details for the Current Context - Context ID: [%d]", cid);
394                                         break;
395                                 }
396
397                                 /* Free tokens */
398                                 tcore_at_tok_free(tokens);
399                                 tokens = NULL;
400
401                                 /* Move to next line */
402                                 pRespData = pRespData->next;
403                         }
404
405                         /* Read primary DNS */
406                         {
407                                 token_dns = g_slist_nth_data(tokens, 1);
408
409                                 /* Strip off starting " and ending " from this token to read actual PDP address */
410                                 dns_prim = tcore_at_tok_extract((void *)token_dns);
411                                 dbg("Primary DNS: [%s]", dns_prim);
412                         }
413
414                         /* Read Secondary DNS */
415                         {
416                                 token_dns = g_slist_nth_data(tokens, 2);
417
418                                 /* Strip off starting " and ending " from this token to read actual PDP address */
419                                 dns_sec = tcore_at_tok_extract((void *)token_dns);
420                                 dbg("Secondary DNS: [%s]", dns_sec);
421                         }
422
423                         if ((g_strcmp0("0.0.0.0", dns_prim) == 0)
424                                         && (g_strcmp0("0.0.0.0", dns_sec) == 0)) {
425                                 dbg("Invalid DNS");
426
427                                 g_free(dns_prim);
428                                 g_free(dns_sec);
429
430                                 tcore_at_tok_free(tokens);
431                                 tokens = NULL;
432
433                                 goto exit_fail;
434                         }
435
436                         __convert_ipv4_atoi(ps_data->data_call_conf.primary_dns,  dns_prim);
437                         __convert_ipv4_atoi(ps_data->data_call_conf.secondary_dns,  dns_sec);
438
439                         tcore_util_hex_dump("   ", 4, ps_data->data_call_conf.primary_dns);
440                         tcore_util_hex_dump("   ", 4, ps_data->data_call_conf.secondary_dns);
441
442                         /* Set DNS Address */
443                         tcore_context_set_dns1(ps_data->ps_context, dns_prim);
444                         tcore_context_set_dns2(ps_data->ps_context, dns_sec);
445
446                         g_free(dns_prim);
447                         g_free(dns_sec);
448
449                         tcore_at_tok_free(tokens);
450                         tokens = NULL;
451                         goto exit_success;
452                 } else {
453                         dbg("No data present in the Response");
454                 }
455         }
456         dbg("Response NOK");
457
458 exit_fail:
459         dbg("Adding default DNS");
460
461         __convert_ipv4_atoi(ps_data->data_call_conf.primary_dns, "8.8.8.8");
462         __convert_ipv4_atoi(ps_data->data_call_conf.secondary_dns, "8.8.4.4");
463
464         tcore_context_set_dns1(ps_data->ps_context, (const char *)ps_data->data_call_conf.primary_dns);
465         tcore_context_set_dns2(ps_data->ps_context, (const char *)ps_data->data_call_conf.secondary_dns);
466
467 exit_success:
468         /* Mount network interface */
469         if (tcore_hal_setup_netif(h, co_ps, on_setup_pdp, (void *)ps_data, cid, TRUE)
470                         != TCORE_RETURN_SUCCESS) {
471                 err("Setup network interface failed");
472                 return;
473         }
474
475         dbg("EXIT : Without error");
476 }
477
478 static TReturn send_get_dns_cmd(CoreObject *co_ps, struct ps_user_data *ps_data)
479 {
480         TcoreHal *hal = NULL;
481         TcorePending *pending = NULL;
482         char *cmd_str = NULL;
483
484         dbg("Entry");
485         hal = tcore_object_get_hal(co_ps);
486
487         cmd_str = g_strdup("AT+XDNS?");
488         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
489
490         pending = tcore_at_pending_new(co_ps, cmd_str, "+XDNS", TCORE_AT_MULTILINE,
491                                                                    on_response_get_dns_cmnd, (void *)ps_data);
492         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
493                 g_free(cmd_str);
494                 return TCORE_RETURN_SUCCESS;
495         }
496         _unable_to_get_pending(co_ps, ps_data->ps_context);
497         g_free(cmd_str);
498         return TCORE_RETURN_FAILURE;
499 }
500
501 static void on_response_get_pdp_address(TcorePending *p, int data_len, const void *data, void *user_data)
502 {
503         const TcoreATResponse *resp = data;
504         CoreObject *co_ps = tcore_pending_ref_core_object(p);
505         GSList *tokens = NULL;
506         const char *line;
507         char *token_pdp_address = NULL;
508         char *token_address = NULL;
509         CoreObject *ps_context = user_data;
510         struct ps_user_data *ps_data = {0, };
511
512         dbg("Enetered");
513
514         if (resp->final_response) {
515                 ps_data = g_try_malloc0(sizeof(struct ps_user_data));
516                 if (ps_data == NULL) {
517                         err("Memory allocation failed!!");
518                         return;
519                 }
520                 ps_data->ps_context = ps_context;
521                 dbg("RESPONSE OK");
522                 if (resp->lines != NULL) {
523                         line = (const char *) resp->lines->data;
524                         tokens = tcore_at_tok_new(line);
525                         if (g_slist_length(tokens) < 2) {
526                                 msg("Invalid message");
527                                 goto error;
528                         }
529                         dbg("Received Data: [%s]", line);
530
531                         /* CID is already stored in ps_context, skip over & read PDP address */
532                         token_address = g_slist_nth_data(tokens, 1);
533                         token_pdp_address = tcore_at_tok_extract((void *)token_address);
534                         dbg("IP Address: [%s]", token_pdp_address);
535
536                         __convert_ipv4_atoi(ps_data->data_call_conf.ip_address,  token_pdp_address);
537
538                         tcore_util_hex_dump("   ", 4, ps_data->data_call_conf.ip_address);
539
540                         /* Strip off starting " and ending " from this token to read actual PDP address */
541                         /* Set IP Address */
542                         (void)tcore_context_set_address(ps_context, (const char *)ps_data->data_call_conf.ip_address);
543
544                         g_free(token_pdp_address);
545                 }
546
547                 /* Get DNS Address */
548                 (void) send_get_dns_cmd(co_ps, ps_data);
549         } else {
550                 dbg("Response NOK");
551
552                 /*without PDP address we will not be able to start packet service*/
553                 tcore_ps_deactivate_context(co_ps, ps_context, NULL);
554         }
555 error:
556         tcore_at_tok_free(tokens);
557         return;
558 }
559
560 static TReturn send_get_pdp_address_cmd(CoreObject *co_ps, CoreObject *ps_context)
561 {
562         TcoreHal *hal = NULL;
563         TcorePending *pending = NULL;
564         unsigned int cid = PS_INVALID_CID;
565         char *cmd_str = NULL;
566
567         dbg("Entry");
568         hal = tcore_object_get_hal(co_ps);
569
570         cid = tcore_context_get_id(ps_context);
571         cmd_str = g_strdup_printf("AT+CGPADDR=%d", cid);
572
573         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
574
575         pending = tcore_at_pending_new(co_ps, cmd_str, "+CGPADDR", TCORE_AT_SINGLELINE,
576                                                                    on_response_get_pdp_address, ps_context);
577         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
578                 g_free(cmd_str);
579                 return TCORE_RETURN_SUCCESS;
580         }
581         _unable_to_get_pending(co_ps, ps_context);
582         g_free(cmd_str);
583         return TCORE_RETURN_FAILURE;
584 }
585
586 static void on_response_send_pdp_activate_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
587 {
588         CoreObject *co_ps = NULL;
589         const TcoreATResponse *resp = data;
590         CoreObject *ps_context = user_data;
591
592         int cid;
593         cid = tcore_context_get_id(ps_context);
594
595
596         dbg("Entry");
597         if (!p)
598                 goto error;
599
600         co_ps = tcore_pending_ref_core_object(p);
601
602         if (resp->success) {
603                 dbg("Response OK");
604
605                 /* Getting the IP address and DNS from the modem */
606                 dbg("Getting IP Address");
607                 (void) send_get_pdp_address_cmd(co_ps, ps_context);
608                 return;
609         } else {
610                 dbg("Unable to activate PDP context - Context ID: [%d]", cid);
611                 dbg("Undefining PDP context");
612                 (void) tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
613                 send_undefine_context_cmd(co_ps, ps_context);
614                 return;
615         }
616 error:
617         {
618                 _unable_to_get_pending(co_ps, ps_context);
619                 return;
620         }
621 }
622
623 static TReturn send_pdp_activate_cmd(CoreObject *co_ps, CoreObject *ps_context)
624 {
625         TcoreHal *hal = NULL;
626         TcorePending *pending = NULL;
627         char *cmd_str = NULL;
628         int cid = 0;
629
630         dbg("Entry");
631
632         /* FIXME: Before MUX setup, use PHY HAL directly. */
633         hal = tcore_object_get_hal(co_ps);
634
635         /*Getting Context ID from Core Object*/
636         cid = tcore_context_get_id(ps_context);
637         cmd_str = g_strdup_printf("AT+CGACT=%d,%d", AT_PDP_ACTIVATE, cid);
638
639         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
640
641         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
642                                                                    on_response_send_pdp_activate_cmd, ps_context);
643         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
644                 g_free(cmd_str);
645                 return TCORE_RETURN_SUCCESS;
646         }
647         _unable_to_get_pending(co_ps, ps_context);
648         g_free(cmd_str);
649         return TCORE_RETURN_FAILURE;
650 }
651
652 static TReturn activate_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
653 {
654         dbg("Entry");
655         return send_pdp_activate_cmd(co_ps, ps_context);
656 }
657
658 static void on_response_send_pdp_deactivate_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
659 {
660         CoreObject *co_ps = NULL;
661         const TcoreATResponse *resp = data;
662         CoreObject *ps_context = user_data;
663         TcoreHal *hal = NULL;
664         unsigned char context_id = 0;
665
666         dbg("Entry");
667         if (resp->success) {
668                 dbg("Response Ok");
669                 if (!p) {
670                         err("Invalid pending data");
671                         goto OUT;
672                 }
673                 co_ps = tcore_pending_ref_core_object(p);
674                 hal = tcore_object_get_hal(co_ps);
675                 context_id = tcore_context_get_id(ps_context);
676                 dbg("Context ID : %d", context_id);
677                 goto OUT;
678         } else {
679                 /* Since PDP deactivation failed, no need to move to
680                  * PS_DATA_CALL_NOT_CONNECTED state
681                  */
682                 err("Response NOk");
683                 return;
684         }
685 OUT:
686         _unable_to_get_pending(co_ps, ps_context);
687
688         if (tcore_hal_setup_netif(hal, co_ps, NULL, NULL, context_id, FALSE) != TCORE_RETURN_SUCCESS)
689                 err("Failed to disable network interface");
690 }
691
692 static TReturn send_pdp_deactivate_cmd(CoreObject *co_ps, CoreObject *ps_context)
693 {
694         TcoreHal *hal = NULL;
695         TcorePending *pending = NULL;
696         char *cmd_str = NULL;
697         int cid = 0;
698
699         dbg("Entry");
700
701         hal = tcore_object_get_hal(co_ps);
702
703         /*Getting Context ID from Core Object*/
704         cid = tcore_context_get_id(ps_context);
705         cmd_str = g_strdup_printf("AT+CGACT=%d,%u", AT_PDP_DEACTIVATE, cid);
706
707         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
708
709         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
710                                                                    on_response_send_pdp_deactivate_cmd, ps_context);
711         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
712                 g_free(cmd_str);
713                 return TCORE_RETURN_SUCCESS;
714         }
715         g_free(cmd_str);
716         return TCORE_RETURN_FAILURE;
717 }
718
719 static TReturn deactivate_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
720 {
721         dbg("Entry");
722         return send_pdp_deactivate_cmd(co_ps, ps_context);
723 }
724 static void on_response_xdns_enable_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
725 {
726         TcoreATResponse *resp = (TcoreATResponse *) data;
727         CoreObject *co_ps = tcore_pending_ref_core_object(p);
728         CoreObject *ps_context = user_data;
729         struct tnoti_ps_call_status noti = {0};
730         int cid = -1;
731
732         dbg("Entry");
733
734         cid = tcore_context_get_id(ps_context);
735
736         if (resp->success) {
737                 dbg("Response OK");
738                 dbg("DNS address getting is Enabled");
739                 noti.context_id = cid;
740                 noti.state = PS_DATA_CALL_CTX_DEFINED;
741         } else {
742                 dbg("Response NOK");
743                 noti.context_id = cid;
744                 noti.state = PS_DATA_CALL_NOT_CONNECTED;
745                 /*If response to enable the DNS NOK then we will use google DNS for the PDP context*/
746         }
747
748         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps,
749                                                                    TNOTI_PS_CALL_STATUS, sizeof(struct tnoti_ps_call_status), &noti);
750         return;
751 }
752
753 static TReturn send_xdns_enable_cmd(CoreObject *co_ps, CoreObject *ps_context)
754 {
755         TcoreHal *hal = NULL;
756         TcorePending *pending = NULL;
757         int cid = -1;
758         char *cmd_str = NULL;
759
760         dbg("Entry");
761
762         hal = tcore_object_get_hal(co_ps);
763         cid = tcore_context_get_id(ps_context);
764
765         cmd_str = g_strdup_printf("AT+XDNS=%d,%d", cid, AT_XDNS_ENABLE);
766         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
767
768         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
769                                                                    on_response_xdns_enable_cmd, ps_context);
770         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
771                 g_free(cmd_str);
772                 return TCORE_RETURN_SUCCESS;
773         }
774         _unable_to_get_pending(co_ps, ps_context);
775         g_free(cmd_str);
776         return TCORE_RETURN_FAILURE;
777 }
778
779 static void on_response_define_pdp_context(TcorePending *p, int data_len, const void *data, void *user_data)
780 {
781         const TcoreATResponse *resp = data;
782         CoreObject *ps_context = (CoreObject *) user_data;
783         CoreObject *co_ps = tcore_pending_ref_core_object(p);
784
785         dbg("Entry");
786         if (resp->success) {
787                 dbg("Response OK");
788                 send_xdns_enable_cmd(co_ps, ps_context);
789         } else {
790                 dbg("response NOK");
791                 _unable_to_get_pending(co_ps, ps_context);
792                 dbg("Exiting");
793         }
794         return;
795 }
796
797 static TReturn define_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
798 {
799         TcoreHal *hal = NULL;
800         TcorePending *pending = NULL;
801         char *apn = NULL;
802         char *cmd_str = NULL;
803         char *pdp_type_str = NULL;
804         unsigned int cid = PS_INVALID_CID;
805         enum co_context_type pdp_type;
806         enum co_context_d_comp d_comp;
807         enum co_context_h_comp h_comp;
808
809         dbg("Entry");
810
811         cid = tcore_context_get_id(ps_context);
812         pdp_type = tcore_context_get_type(ps_context);
813         d_comp = tcore_context_get_data_compression(ps_context);
814         h_comp = tcore_context_get_header_compression(ps_context);
815         apn = tcore_context_get_apn(ps_context);
816
817         hal = tcore_object_get_hal(co_ps);
818         switch (pdp_type) {
819         case CONTEXT_TYPE_X25:
820         {
821                 dbg("CONTEXT_TYPE_X25");
822                 pdp_type_str = g_strdup_printf("X.25");
823         }
824         break;
825
826         case CONTEXT_TYPE_IPV4V6:
827         case CONTEXT_TYPE_IP:
828         {
829                 dbg("CONTEXT_TYPE_IP");
830                 pdp_type_str = g_strdup_printf("IP");
831         }
832         break;
833
834         case CONTEXT_TYPE_PPP:
835         {
836                 dbg("CONTEXT_TYPE_PPP");
837                 pdp_type_str = g_strdup_printf("PPP");
838         }
839         break;
840
841         case CONTEXT_TYPE_IPV6:
842         {
843                 dbg("CONTEXT_TYPE_IPV6");
844                 pdp_type_str = g_strdup_printf("IPV6");
845                 break;
846         }
847
848         default:
849         {
850                 /*PDP Type not supported supported*/
851                 dbg("Unsupported PDP type: %d returning ", pdp_type);
852                 g_free(apn);
853                 return TCORE_RETURN_FAILURE;
854         }
855         }
856         dbg("Activating context for CID: %d", cid);
857         cmd_str = g_strdup_printf("AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d",
858                         cid, pdp_type_str, apn, d_comp, h_comp);
859
860         dbg("Command: [%s] Command Length: [%d]", cmd_str, strlen(cmd_str));
861         g_free(apn);
862
863         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
864                                                                    on_response_define_pdp_context, ps_context);
865         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
866                 g_free(cmd_str);
867                 g_free(pdp_type_str);
868                 return TCORE_RETURN_SUCCESS;
869         }
870         _unable_to_get_pending(co_ps, ps_context);
871         g_free(cmd_str);
872         g_free(pdp_type_str);
873         return TCORE_RETURN_FAILURE;
874 }
875
876 static struct tcore_ps_operations ps_ops = {
877         .define_context = define_ps_context,
878         .activate_context = activate_ps_context,
879         /* Use AT_standard entry point */
880         .deactivate_context = deactivate_ps_context,
881 };
882
883 gboolean imc_ps_init(TcorePlugin *cp, CoreObject *co_ps)
884 {
885         TcorePlugin *plugin = tcore_object_ref_plugin(co_ps);
886
887         dbg("Entry");
888
889         /* Set operations */
890         tcore_ps_set_ops(co_ps, &ps_ops, TCORE_OPS_TYPE_CP);
891
892         tcore_object_add_callback(co_ps, "+CGEV", on_cgev_notification, NULL);
893         tcore_object_add_callback(co_ps, "+XNOTIFYDUNSTATUS", on_event_dun_call_notification, plugin);
894
895         dbg("Exit");
896
897         return TRUE;
898 }
899
900 void imc_ps_exit(TcorePlugin *cp, CoreObject *co_ps)
901 {
902         dbg("Exit");
903 }