Fixed code formatting issues and end of line(LF) to UNIX style
[profile/ivi/tel-plugin-imc.git] / src / s_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 "s_common.h"
44 #include "s_ps.h"
45
46
47
48 #define VNET_CH_PATH_BOOT0  "/dev/umts_boot0"
49 #define IOCTL_CG_DATA_SEND  _IO('o', 0x37)
50
51 /*Invalid Session ID*/
52 #define PS_INVALID_CID  999 /*Need to check */
53
54 /*Maximum String length Of the Command*/
55 #define MAX_AT_CMD_STR_LEN  150
56
57 /*Command for PDP activation and Deactivation*/
58 #define AT_PDP_ACTIVATE 1
59 #define AT_PDP_DEACTIVATE 0
60
61 #define AT_XDNS_ENABLE 1
62 #define AT_XDNS_DISABLE 0
63 #define AT_SESSION_DOWN 0
64 static void _ps_free(void *ptr)
65 {
66         dbg("Entered");
67         if (ptr) {
68                 (void) free(ptr);
69                 ptr = NULL;
70         }
71         dbg("Exit");
72         return;
73 }
74 static void _unable_to_get_pending(CoreObject *co_ps, CoreObject *ps_context)
75 {
76         struct tnoti_ps_call_status data_resp = {0};
77         dbg("Entered");
78         data_resp.context_id = tcore_context_get_id(ps_context);
79         data_resp.state = AT_SESSION_DOWN; /*check value of state*/
80         data_resp.result = 0xFF; /*check error value*/
81         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps,
82                                                                    TNOTI_PS_CALL_STATUS, sizeof(struct tnoti_ps_call_status), &data_resp);
83         (void) tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
84         dbg("Exit");
85 }
86 static TReturn _pdp_device_control(unsigned int cid)
87 {
88         int fd = -1;
89         int ret = -1;
90         fd = open(VNET_CH_PATH_BOOT0, O_RDWR);
91         if (fd < 0) {
92                 dbg("error : open [ %s ] [ %s ]", VNET_CH_PATH_BOOT0, strerror(errno));
93                 return -1;
94         }
95         /*To Do for different Cids*/
96         dbg("Send IOCTL: arg 0x05 (0101) HSIC1, cid=%d \n", cid);
97         if (cid == 1) {
98                 ret = ioctl(fd, IOCTL_CG_DATA_SEND, 0x05);
99         } else if (cid == 2) {
100                 ret = ioctl(fd, IOCTL_CG_DATA_SEND, 0xA);
101         } else {
102                 dbg("More Than 2 context are not supported right Now");
103         }
104         close(fd);
105         if (ret < 0) {
106                 dbg("[ error ] send IOCTL_CG_DATA_SEND (0x%x) fail!! \n", IOCTL_CG_DATA_SEND);
107                 return TCORE_RETURN_FAILURE;
108         } else {
109                 dbg("[ ok ] send IOCTL_CG_DATA_SEND (0x%x) success!! \n", IOCTL_CG_DATA_SEND);
110                 return TCORE_RETURN_SUCCESS;
111         }
112 }
113
114 static gboolean on_event_cgev_handle(CoreObject *co_ps, const void *data, void *user_data)
115 {
116         char *token = NULL;
117         GSList *tokens = NULL;
118         GSList *lines = NULL;
119         const char *line = NULL;
120         char *noti_data = NULL;
121         int i = 0;
122         int value = 20;
123         int state = -1;
124         struct tnoti_ps_call_status data_resp = {0};
125
126         dbg("Entered");
127         lines = (GSList *) data;
128         line = (const char *) lines->data;
129         dbg("Lines->data :-%s", line);
130
131         tokens = tcore_at_tok_new(line);
132         switch (g_slist_length(tokens)) {
133         case 0:
134         {
135                 dbg("No token present: Ignore +CGEV Notifications ");
136                 return TRUE;
137         }
138
139         case 1:
140         {
141                 dbg("one Token present");
142                 noti_data = g_slist_nth_data(tokens, 0);
143                 dbg("notification data :-%s", noti_data);
144                 if (0 == strcmp(noti_data, "ME CLASS B")) {
145                         dbg("ME Class B notification received");
146                         goto ignore;
147                 }
148                 if (0 == strcmp(noti_data, "NW CLASS A")) {
149                         dbg("NW Class A notification received");
150                         goto ignore;
151                 }
152                 token = strtok(noti_data, " ");
153                 while (token != NULL) {
154                         if ((i == 0) && (0 != strcmp(token, "ME"))) {
155                                 break;
156                         }
157                         if ((i == 1) && (0 != strcmp(token, "PDN"))) {
158                                 break;
159                         }
160                         if ((i == 2) && (0 == strcmp(token, "ACT"))) {
161                                 state = 1;
162                         }
163                         if ((i == 2) && (0 == strcmp(token, "DEACT"))) {
164                                 state = 0;
165                         }
166                         if (i == 3) {
167                                 value = atoi(token);
168                                 break;
169                         }
170                         i++;
171                         token = strtok(NULL, " ");
172                 }
173                 dbg("value:%d ", value);
174                 i = 0;
175                 break;
176         }
177
178         case 3:
179         {
180                 i = 0;
181                 state = 0;
182                 value = 0;
183                 dbg("Three Token present");
184                 noti_data = g_slist_nth_data(tokens, 0);
185                 dbg("notification data :-%s", noti_data);
186                 token = strtok(noti_data, " ");
187                 while (token != NULL) {
188                         if ((i == 0) && (0 == strcmp(token, "ME"))) {
189                                 state = 1;
190                         }
191                         if ((i == 1) && (0 != strcmp(token, "DEACT"))) {
192                                 break;
193                         }
194                         if ((i == 2) && (0 == strcmp(token, "\"IP\"")) && (0 == state)) {
195                                 dbg("MObile Deactiavted the Context");
196                                 value = 10;
197                                 break;
198                         }
199                         if ((i == 2) && (0 == strcmp(token, "\"IP\"")) && (1 == state)) {
200                                 dbg("NW Deactiavted the Context");
201                                 value = 10;
202                                 break;
203                         }
204                         i++;
205                         token = strtok(NULL, " ");
206                 }
207                 if (value == 10 && state == 0) {
208                         dbg("Recieved Notification for Context deactivations from network");
209                         noti_data = g_slist_nth_data(tokens, 1);
210                         dbg("PDP Address :- %s", noti_data);
211                         noti_data = g_slist_nth_data(tokens, 2);
212                         dbg("CID got deactivated :- %d", atoi(noti_data));
213                 }
214                 if (value == 10 && state == 1) {
215                         dbg("Recieved Notification for Context deactivations from Mobile");
216                         noti_data = g_slist_nth_data(tokens, 1);
217                         dbg("PDP Address :- %s", noti_data);
218                         noti_data = g_slist_nth_data(tokens, 2);
219                         dbg("CID got deactivated :- %d", atoi(noti_data));
220                 }
221                 data_resp.context_id = atoi(noti_data);
222                 data_resp.state = 3;        /*check value of state*/
223                 dbg("State of the service :- %d", data_resp.state);
224                 data_resp.result = 0xFF;       /*check error value*/
225                 dbg("Sending the notification");
226
227                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps,
228                                                                            TNOTI_PS_CALL_STATUS, sizeof(struct tnoti_ps_call_status), &data_resp);
229
230                 state = 100;
231                 value = 100;
232
233                 break;
234         }
235
236         default:
237         {
238                 dbg("Ignore +CGEV Notifications ");
239         }
240         }
241         if (state == 1) {
242                 dbg("Notification recieved for Activation of CID:-%d", value);
243         } else if (state == 0) {
244                 dbg("Notification recieved for Deactivation of CID:-%d", value);
245         } else {
246                 dbg("ignore");
247         }
248 ignore:
249         tcore_at_tok_free(tokens);
250         return TRUE;
251 }
252
253 static gboolean on_event_dun_call_notification(CoreObject *o, const void *data, void *user_data)
254 {
255         GSList *tokens = NULL;
256         const char *line = NULL;
257         int value = 0;
258         GSList *lines = NULL;
259         dbg("Entered");
260
261         lines = (GSList *) data;
262         if (1 != g_slist_length(lines)) {
263                 dbg("unsolicited msg but multiple line");
264                 goto OUT;
265         }
266         line = (char *) (lines->data);
267         tokens = tcore_at_tok_new(line);
268         value = atoi(g_slist_nth_data(tokens, 0));
269
270         /*
271         <status> may be
272         0: DUN activation in progress
273         1: DUN deactivation in progress
274         2: DUN activated
275         3: DUN deactivated
276         */
277         switch (value) {
278         case 0:    /*Fall Through*/
279         case 1:
280         {
281                 break;
282         }
283
284         case 2:
285         {
286                 /*To Do:- Fill Data structure : data*/
287                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
288                                                                            TNOTI_PS_EXTERNAL_CALL, sizeof(struct tnoti_ps_external_call), &data);
289         }
290
291         case 3:
292         {
293                 /*To Do:- Fill Data structure : data*/
294                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
295                                                                            TNOTI_PS_EXTERNAL_CALL, sizeof(struct tnoti_ps_external_call), &data);
296         }
297         break;
298
299         default:
300                 goto OUT;
301         }
302 OUT:
303         if (NULL != tokens) {
304                 tcore_at_tok_free(tokens);
305         }
306         return TRUE;
307 }
308 static void on_response_undefine_context_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
309 {
310         CoreObject *co_ps = NULL;
311         const TcoreATResponse *resp = data;
312         CoreObject *ps_context = user_data;
313         dbg("Entered");
314         co_ps = tcore_pending_ref_core_object(p);
315         if (resp->success) {
316                 dbg("Response Ok");
317                 return;
318         }
319         dbg("Response NOk");
320         _unable_to_get_pending(co_ps, ps_context);
321         return;
322 }
323
324 static void send_undefine_context_cmd(CoreObject *co_ps, CoreObject *ps_context)
325 {
326         TcoreHal *hal = NULL;
327         TcorePending *pending = NULL;
328         char cmd_str[MAX_AT_CMD_STR_LEN];
329         int cid = 0;
330
331         dbg("Entered");
332         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
333
334         /* FIXME: Before MUX setup, use PHY HAL directly. */
335         hal = tcore_object_get_hal(co_ps);
336
337         /*Getting Context ID from Core Object*/
338         cid = tcore_context_get_id(ps_context);
339
340         (void) sprintf(cmd_str, "AT+CGDCONT=%d", cid);
341         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
342                                                                    on_response_undefine_context_cmd, ps_context);
343         if (NULL == pending) {
344                 err("Unable to get the create a AT request ");
345                 goto error;
346         }
347         tcore_hal_send_request(hal, pending);
348         dbg("Exit: Successfully");
349         return;
350 error:
351         {
352                 dbg("Exit: With error");
353                 _unable_to_get_pending(co_ps, ps_context);
354                 return;
355         }
356 }
357 static void on_response_data_counter_command(TcorePending *p, int data_len, const void *data, void *user_data)
358 {
359         CoreObject *ps_context = user_data;
360         const TcoreATResponse *resp = data;
361         CoreObject *co_ps = tcore_pending_ref_core_object(p);
362
363         GSList *tokens = NULL;
364         GSList *pRespData;
365         const char *line = NULL;
366         int no_pdp_active = 0;
367         unsigned long long Rx;
368         unsigned long long Tx;
369         int cid = tcore_context_get_id(ps_context);
370         dbg("Entered");
371
372         if (resp->final_response) {
373                 dbg("Response OK");
374                 dbg(" response lines : -%s", resp->lines);
375                 if (resp->lines) {
376                         pRespData = (GSList *) resp->lines;
377                         no_pdp_active = g_slist_length(pRespData);
378                         dbg("Total Number of Active PS Context :- %d", no_pdp_active);
379
380                         if (no_pdp_active == 0) {
381                                 return;
382                         }
383                         while (pRespData) {
384                                 dbg("Entered the Loop pRespData");
385
386                                 line = (const char *) pRespData->data;
387                                 dbg("Response->lines->data :%s", line);
388                                 tokens = tcore_at_tok_new(line);
389                                 if (cid == atoi(g_slist_nth_data(tokens, 0))) {
390                                         dbg("Found the data for our CID");
391                                         Tx = (unsigned long long) g_ascii_strtoull((g_slist_nth_data(tokens, 1)), NULL, 10);
392                                         dbg("Tx: %d", Tx);
393
394                                         Rx = (unsigned long long) g_ascii_strtoull((g_slist_nth_data(tokens, 2)), NULL, 10);
395                                         dbg("Rx: %d", Rx);
396
397                                         tcore_at_tok_free(tokens);
398                                         tokens = NULL;
399                                         dbg("Exiting the Loop pRespData");
400                                         break;
401                                 }
402                                 tcore_at_tok_free(tokens);
403                                 tokens = NULL;
404                                 pRespData = pRespData->next;
405                         }
406                         dbg("Sending Data counter notifications");
407
408                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps,
409                                                                                    TNOTI_PS_CURRENT_SESSION_DATA_COUNTER, 0, NULL);
410                         return;
411                 } else {
412                         dbg("No Active PS Context");
413                 }
414         }
415         dbg("Response NOK");
416 }
417
418 static TReturn send_data_counter_command(CoreObject *co_ps, CoreObject *ps_context)
419 {
420         TcoreHal *hal = NULL;
421         TcorePending *pending = NULL;
422         char cmd_str[MAX_AT_CMD_STR_LEN];
423
424         dbg("Enetered");
425         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
426
427         hal = tcore_object_get_hal(co_ps);
428
429         (void) sprintf(cmd_str, "AT+XGCNTRD");
430         pending = tcore_at_pending_new(co_ps, cmd_str, "+XGCNTRD", TCORE_AT_MULTILINE,
431                                                                    on_response_data_counter_command, ps_context);
432         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
433                 return TCORE_RETURN_SUCCESS;
434         }
435         _unable_to_get_pending(co_ps, ps_context);
436         return TCORE_RETURN_FAILURE;
437 /*Add code if unable to get the data usage*/
438 }
439 static void on_response_deactivate_ps_context(TcorePending *p, int data_len, const void *data, void *user_data)
440 {
441         CoreObject *co_ps = tcore_pending_ref_core_object(p);
442         CoreObject *ps_context = user_data;
443         const TcoreATResponse *resp = data;
444         int cid;
445
446         cid = tcore_context_get_id(ps_context);
447         if (resp->success) {
448                 dbg("Response OK");
449                 /*get the data usage and report it application*/
450                 (void) send_data_counter_command(co_ps, ps_context);
451                 /*get the HSDPA status and report it to server*/
452         } else {
453                 dbg("Response NOK");
454                 send_undefine_context_cmd(co_ps, ps_context);
455         }
456         return;
457 }
458
459 static TReturn deactivate_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
460 {
461         TcoreHal *hal = NULL;
462         TcorePending *pending = NULL;
463         unsigned int cid = PS_INVALID_CID;
464         char cmd_str[MAX_AT_CMD_STR_LEN];
465
466         dbg("Entered");
467         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
468
469         /*Getting Context ID from Core Object*/
470         cid = tcore_context_get_id(ps_context);
471
472         /* FIXME: Before MUX setup, use PHY HAL directly. */
473         hal = tcore_object_get_hal(co_ps);
474
475         (void) sprintf(cmd_str, "AT+CGACT=%d,%d", AT_PDP_DEACTIVATE, cid);
476         dbg("At commands :- %s", cmd_str);
477
478         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
479                                                                    on_response_deactivate_ps_context, ps_context);
480         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
481                 (void) tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATING);
482                 return TCORE_RETURN_SUCCESS;
483         }
484         _unable_to_get_pending(co_ps, ps_context);
485         return TCORE_RETURN_FAILURE;
486 }
487
488 static void on_response_get_dns_cmnd(TcorePending *p, int data_len, const void *data, void *user_data)
489 {
490         struct tnoti_ps_pdp_ipconfiguration noti = {0};
491         struct tnoti_ps_call_status data_status = {0};
492         char devname[10] = {0, };
493         char *dns_prim = NULL;
494         char *dns_sec = NULL;
495         char *pdp_address = NULL;
496         char addr[4] = {0};
497         GSList *tokens = NULL;
498         GSList *pRespData;
499         const char *line = NULL;
500         char *token_dns = NULL;
501         char *token_add = NULL;
502
503         char *token_pdp_address = NULL;
504         int no_pdp_active = 0;
505         int index = 0;
506
507         CoreObject *ps_context = user_data;
508         const TcoreATResponse *resp = data;
509         CoreObject *co_ps = tcore_pending_ref_core_object(p);
510         int cid = tcore_context_get_id(ps_context);
511
512         dbg("Entered");
513
514         if (resp->final_response) {
515                 dbg("Response OK");
516                 if (resp->lines) {
517                         dbg("DNS data present in the Response");
518                         pRespData = (GSList *) resp->lines;
519                         no_pdp_active = g_slist_length(pRespData);
520                         dbg("Total Number of Active PS Context :- %d", no_pdp_active);
521                         if (0 == no_pdp_active) {
522                                 goto exit_fail;
523                         }
524                         while (pRespData) {
525                                 dbg("traversing the DNS data for each active context");
526                                 line = (const char *) pRespData->data;
527                                 dbg("Response->lines->data :%s", line);
528                                 tokens = tcore_at_tok_new(line);
529                                 if (cid == atoi(g_slist_nth_data(tokens, 0))) {
530                                         dbg("Found the DNS details for the Current context");
531                                         dbg("Context Id of The Context : %d", atoi(g_slist_nth_data(tokens, 0)));
532                                         break;
533                                 }
534                                 tcore_at_tok_free(tokens);
535                                 tokens = NULL;
536                                 pRespData = pRespData->next;
537                         }
538                         { /* Read primary DNS */
539                                 token_dns = g_slist_nth_data(tokens, 1);
540                                 /* Strip off starting " and ending " from this token to read actual PDP address */
541                                 dns_prim = util_removeQuotes((void *) token_dns);
542                                 dbg("Token_dns :%s", token_dns);
543                                 dbg("Primary DNS :- %s", dns_prim);
544                                 index = 0;
545                                 token_add = strtok(dns_prim, ".");
546                                 while (token_add != NULL) {
547                                         noti.primary_dns[index++] = atoi(token_add);
548                                         token_add = strtok(NULL, ".");
549                                 }
550                                 _ps_free(dns_prim);
551                         }
552                         { /* Read Secondary DNS */
553                                 token_add = NULL;
554                                 token_dns = g_slist_nth_data(tokens, 2);
555                                 dns_sec = util_removeQuotes((void *) token_dns);
556
557                                 dbg("Token_dns :%s", token_dns);
558                                 dbg("Secondary DNS :- %s", dns_sec);
559                                 index = 0;
560                                 token_add = strtok(dns_sec, ".");
561                                 while (token_add != NULL) {
562                                         noti.secondary_dns[index++] = atoi(token_add);
563                                         token_add = strtok(NULL, ".");
564                                 }
565                                 _ps_free(dns_sec);
566                         }
567                         tcore_at_tok_free(tokens);
568                         tokens = NULL;
569                         goto exit_success;
570                 } else {
571                         dbg("No data present in the Response");
572                 }
573         }
574         dbg("Response NOK");
575 exit_fail:
576         {
577                 dbg("Adding default DNS");
578                 dbg("Adding the Primary DNS");
579                 noti.primary_dns[0] = 8;
580                 noti.primary_dns[1] = 8;
581                 noti.primary_dns[2] = 8;
582                 noti.primary_dns[3] = 8;
583                 dbg("Adding Secondary DNS");
584                 noti.secondary_dns[0] = 8;
585                 noti.secondary_dns[1] = 8;
586                 noti.secondary_dns[2] = 4;
587                 noti.secondary_dns[3] = 4;
588         }
589 exit_success:
590         {
591                 dbg("Able to get the DNS from the DNS Query");
592                 token_pdp_address = tcore_context_get_address(ps_context);
593                 pdp_address = util_removeQuotes((void *) token_pdp_address);
594
595                 dbg("PDP address :- %s", pdp_address);
596                 /* Store IP address in char array, Telephony expected IP address in this format */
597                 token_add = strtok(pdp_address, ".");
598                 index = 0;
599                 while ((token_add != NULL) && (index < 4)) {   /* Currently only IPv4 is supported */
600                         addr[index++] = atoi(token_add);
601                         token_add = strtok(NULL, ".");
602                 }
603                 _ps_free(pdp_address);
604                 _ps_free((void *) token_pdp_address);
605                 noti.field_flag = (0x0001 & 0x0002 & 0x0004);
606                 noti.err = 0;
607                 noti.context_id = cid;
608                 memcpy(&noti.ip_address, &addr, 4);
609                 if (_pdp_device_control(cid) != TCORE_RETURN_SUCCESS) {
610                         dbg("_pdp_device_control() failed. errno=%d", errno);
611                 }
612                 snprintf(devname, 10, "pdp%d", cid - 1);
613                 memcpy(noti.devname, devname, 10);
614                 dbg("devname = [%s]", devname);
615                 if (tcore_util_netif_up(devname) != TCORE_RETURN_SUCCESS) {
616                         dbg("util_netif_up() failed. errno=%d", errno);
617                 }
618
619                 dbg("Send Notification upwards of IP address");
620                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps, TNOTI_PS_PDP_IPCONFIGURATION,
621                                                                            sizeof(struct tnoti_ps_pdp_ipconfiguration), &noti);
622
623                 data_status.context_id = cid;
624                 data_status.state = 1;
625                 data_status.result = 0;
626
627                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps)), co_ps,
628                                                                            TNOTI_PS_CALL_STATUS, sizeof(struct tnoti_ps_call_status), &data_status);
629                 dbg("EXIT : Without error");
630                 return;
631         }
632 }
633
634 static TReturn send_get_dns_cmd(CoreObject *co_ps, CoreObject *ps_context)
635 {
636         TcoreHal *hal = NULL;
637         TcorePending *pending = NULL;
638         char cmd_str[MAX_AT_CMD_STR_LEN];
639
640         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
641
642         dbg("Entered");
643         hal = tcore_object_get_hal(co_ps);
644
645         (void) sprintf(cmd_str, "AT+XDNS?");
646         pending = tcore_at_pending_new(co_ps, cmd_str, "+XDNS", TCORE_AT_MULTILINE,
647                                                                    on_response_get_dns_cmnd, ps_context);
648         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
649                 return TCORE_RETURN_SUCCESS;
650         }
651         _unable_to_get_pending(co_ps, ps_context);
652         return TCORE_RETURN_FAILURE;
653 }
654
655 static void on_response_get_pdp_address(TcorePending *p, int data_len, const void *data, void *user_data)
656 {
657         const TcoreATResponse *resp = data;
658         CoreObject *co_ps = tcore_pending_ref_core_object(p);
659         CoreObject *ps_context = user_data;
660         GSList *tokens = NULL;
661         const char *line;
662         char *token_pdp_address;
663         dbg("Enetered");
664         if (resp->final_response) {
665                 dbg("RESPONSE OK");
666                 if (resp->lines != NULL) {
667                         dbg("resp->lines present ");
668                         line = (const char *) resp->lines->data;
669                         tokens = tcore_at_tok_new(line);
670                         if (g_slist_length(tokens) < 2) {
671                                 msg("invalid message");
672                                 goto error;
673                         }
674                         dbg("line:- %s", line);
675                         /* CID is already stored in ps_context, skip over & read PDP address */
676                         token_pdp_address = g_slist_nth_data(tokens, 1);
677
678                         dbg("token_pdp_address :- %s", token_pdp_address);
679                         /* Strip off starting " and ending " from this token to read actual PDP address */
680                         (void) tcore_context_set_address(ps_context, (const char *) token_pdp_address);
681                 }
682
683                 (void) send_get_dns_cmd(co_ps, ps_context);
684         } else {
685                 dbg("Response NOK");
686                 /*without PDP address we will not be able to start packet service*/
687                 (void) deactivate_ps_context(co_ps, ps_context, NULL);
688         }
689 error:
690         tcore_at_tok_free(tokens);
691         return;
692 }
693
694 static TReturn send_get_pdp_address_cmd(CoreObject *co_ps, CoreObject *ps_context)
695 {
696         TcoreHal *hal = NULL;
697         TcorePending *pending = NULL;
698         unsigned int cid = PS_INVALID_CID;
699         char cmd_str[MAX_AT_CMD_STR_LEN] = {0};
700
701         dbg("Entered");
702         hal = tcore_object_get_hal(co_ps);
703
704         cid = tcore_context_get_id(ps_context);
705         (void) sprintf(cmd_str, "AT+CGPADDR=%d", cid);
706         pending = tcore_at_pending_new(co_ps, cmd_str, "+CGPADDR", TCORE_AT_SINGLELINE,
707                                                                    on_response_get_pdp_address, ps_context);
708         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
709                 return TCORE_RETURN_SUCCESS;
710         }
711         _unable_to_get_pending(co_ps, ps_context);
712         return TCORE_RETURN_FAILURE;
713 }
714
715 static void on_response_send_pdp_activate_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
716 {
717         CoreObject *co_ps = NULL;
718         const TcoreATResponse *resp = data;
719         CoreObject *ps_context = user_data;
720
721         int cid;
722         cid = tcore_context_get_id(ps_context);
723
724
725         dbg("Entered");
726         if (!p) {
727                 goto error;
728         }
729         co_ps = tcore_pending_ref_core_object(p);
730
731         if (resp->success) {
732                 dbg("Response Ok");
733                 /*getting the IP address and DNS from the modem*/
734                 dbg("Getting the IP Address");
735                 (void) send_get_pdp_address_cmd(co_ps, ps_context);
736                 return;
737         } else {
738                 dbg("Unable to actiavte PDP context for CID: %d ", cid);
739                 dbg("Undefineing the PDP context");
740                 (void) tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
741                 send_undefine_context_cmd(co_ps, ps_context);
742                 return;
743         }
744 error:
745         {
746                 _unable_to_get_pending(co_ps, ps_context);
747                 return;
748         }
749 }
750
751 static TReturn send_pdp_activate_cmd(CoreObject *co_ps, CoreObject *ps_context)
752 {
753         TcoreHal *hal = NULL;
754         TcorePending *pending = NULL;
755         char cmd_str[MAX_AT_CMD_STR_LEN] = {0};
756         int cid = 0;
757         dbg("Entered");
758         /* FIXME: Before MUX setup, use PHY HAL directly. */
759         hal = tcore_object_get_hal(co_ps);
760
761         /*Getting Context ID from Core Object*/
762         cid = tcore_context_get_id(ps_context);
763         (void) sprintf(cmd_str, "AT+CGACT=%d,%d", AT_PDP_ACTIVATE, cid);
764         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
765                                                                    on_response_send_pdp_activate_cmd, ps_context);
766         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
767                 return TCORE_RETURN_SUCCESS;
768         }
769         _unable_to_get_pending(co_ps, ps_context);
770         return TCORE_RETURN_FAILURE;
771 }
772
773 static void on_response_xdns_enable_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
774 {
775         TcoreATResponse *resp = (TcoreATResponse *) data;
776         CoreObject *co_ps = tcore_pending_ref_core_object(p);
777         CoreObject *ps_context = user_data;
778         dbg("Entered");
779         if (resp->success) {
780                 dbg("Response OK");
781                 dbg("DNS address getting is Enabled");
782         } else {
783                 dbg("Response NOK");
784                 /*If response to enable the DNS NOK then we will use google DNS for the PDP context*/
785         }
786         (void) send_pdp_activate_cmd(co_ps, ps_context);
787         return;
788 }
789
790 static TReturn send_xdns_enable_cmd(CoreObject *co_ps, CoreObject *ps_context)
791 {
792         TcoreHal *hal = NULL;
793         TcorePending *pending = NULL;
794         int cid = -1;
795         char cmd_str[MAX_AT_CMD_STR_LEN];
796
797         dbg("Entered");
798         memset(cmd_str, 0x0, MAX_AT_CMD_STR_LEN);
799
800         hal = tcore_object_get_hal(co_ps);
801         cid = tcore_context_get_id(ps_context);
802
803         (void) sprintf(cmd_str, "AT+XDNS=%d,%d", cid, AT_XDNS_ENABLE);
804         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
805                                                                    on_response_xdns_enable_cmd, ps_context);
806         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
807                 return TCORE_RETURN_SUCCESS;
808         }
809         _unable_to_get_pending(co_ps, ps_context);
810         return TCORE_RETURN_FAILURE;
811 }
812
813 static void on_response_define_pdp_context(TcorePending *p, int data_len, const void *data, void *user_data)
814 {
815         const TcoreATResponse *resp = data;
816         CoreObject *ps_context = (CoreObject *) user_data;
817         CoreObject *co_ps = tcore_pending_ref_core_object(p);
818
819         dbg("Entered");
820         if (resp->success) {
821                 dbg("Response OK");
822                 send_xdns_enable_cmd(co_ps, ps_context);
823         } else {
824                 dbg("response NOK");
825                 _unable_to_get_pending(co_ps, ps_context);
826                 dbg("Exiting");
827         }
828         return;
829 }
830
831 static TReturn send_define_pdp_context_cmd(CoreObject *co_ps, CoreObject *ps_context)
832 {
833         TcoreHal *hal = NULL;
834         TcorePending *pending = NULL;
835         char *apn = NULL;
836         char cmd_str[MAX_AT_CMD_STR_LEN] = {0};
837         char pdp_type_str[10] = {0};
838         unsigned int cid = PS_INVALID_CID;
839         enum co_context_type pdp_type;
840         enum co_context_d_comp d_comp;
841         enum co_context_h_comp h_comp;
842
843         dbg("Entered");
844
845         cid = tcore_context_get_id(ps_context);
846         pdp_type = tcore_context_get_type(ps_context);
847         d_comp = tcore_context_get_data_compression(ps_context);
848         h_comp = tcore_context_get_header_compression(ps_context);
849         apn = tcore_context_get_apn(ps_context);
850
851         hal = tcore_object_get_hal(co_ps);
852         switch (pdp_type) {
853         case CONTEXT_TYPE_X25:
854         {
855                 dbg("CONTEXT_TYPE_X25");
856                 strcpy(pdp_type_str, "X.25");
857                 break;
858         }
859
860         case CONTEXT_TYPE_IP:
861         {
862                 dbg("CONTEXT_TYPE_IP");
863                 strcpy(pdp_type_str, "IP");
864         }
865         break;
866
867         case CONTEXT_TYPE_PPP:
868         {
869                 dbg("CONTEXT_TYPE_PPP");
870                 strcpy(pdp_type_str, "PPP");
871         }
872         break;
873
874         case CONTEXT_TYPE_IPV6:
875         {
876                 dbg("CONTEXT_TYPE_IPV6");
877                 strcpy(pdp_type_str, "IPV6");
878                 break;
879         }
880
881         default:
882         {
883                 /*PDP Type not supported supported*/
884                 dbg("Unsupported PDP type :- %d returning ", pdp_type);
885                 return TCORE_RETURN_FAILURE;
886         }
887         }
888         dbg("Activating context for CID :- %d", cid);
889         (void) sprintf(cmd_str, "AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d", cid, pdp_type_str, apn, d_comp, h_comp);
890
891         pending = tcore_at_pending_new(co_ps, cmd_str, NULL, TCORE_AT_NO_RESULT,
892                                                                    on_response_define_pdp_context, ps_context);
893         if (TCORE_RETURN_SUCCESS == tcore_hal_send_request(hal, pending)) {
894                 (void) tcore_context_set_state(ps_context, CONTEXT_STATE_ACTIVATING);
895                 return TCORE_RETURN_SUCCESS;
896         }
897         _unable_to_get_pending(co_ps, ps_context);
898         return TCORE_RETURN_FAILURE;
899 }
900
901 static TReturn activate_ps_context(CoreObject *co_ps, CoreObject *ps_context, void *user_data)
902 {
903         dbg("Entered");
904         return send_define_pdp_context_cmd(co_ps, ps_context);
905 }
906
907
908 static struct tcore_ps_operations ps_ops = {
909         .activate_context = activate_ps_context,
910         .deactivate_context = deactivate_ps_context
911 };
912
913 gboolean s_ps_init(TcorePlugin *p, TcoreHal *hal)
914 {
915         CoreObject *o;
916         struct context *context_table = NULL;
917
918         dbg("Entered");
919         o = tcore_ps_new(p, "umts_ps", &ps_ops, hal);
920
921         if (!o)
922                 return FALSE;
923         tcore_object_link_user_data(o, (void *) context_table);
924
925         tcore_object_add_callback(o, "+CGEV", on_event_cgev_handle, p);
926         tcore_object_add_callback(o, "+XNOTIFYDUNSTATUS", on_event_dun_call_notification, p);
927
928         dbg("Exiting");
929         return TRUE;
930 }
931
932 void s_ps_exit(TcorePlugin *p)
933 {
934         CoreObject *o;
935
936         dbg("Entered");
937         o = tcore_plugin_ref_core_object(p, "umts_ps");
938         if (!o)
939                 return;
940
941         tcore_ps_free(o);
942         dbg("Exiting");
943 }