Tizen 2.1 base
[platform/core/telephony/tel-plugin-atmodem.git] / src / s_ps.c
1 /**
2  * tel-plugin-atmodem
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
7  *          Hayoon Ko       <hayoon.ko@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include <glib.h>
28 #include <arpa/inet.h>
29
30 #include <fcntl.h>
31
32 #include <tcore.h>
33 #include <hal.h>
34 #include <core_object.h>
35 #include <plugin.h>
36 #include <queue.h>
37 #include <co_ps.h>
38 #include <co_context.h>
39 #include <user_request.h>
40 #include <server.h>
41 #include <util.h>
42
43 #include "s_common.h"
44 #include "s_ps.h"
45
46 #include "atchannel.h"
47 #include "at_tok.h"
48
49 extern struct ATResponse *sp_response;
50 extern char *s_responsePrefix;
51 extern enum ATCommandType s_type;
52
53 static void on_confirmation_ps_message_send( TcorePending *p, gboolean result, void *user_data )
54 {
55         UserRequest* ur = NULL;
56         struct ATReqMetaInfo* metainfo = NULL;
57         unsigned int info_len =0;
58         dbg("on_confirmation_ps_message_send - msg out from queue. alloc ATRsp buffer & write rspPrefix if needed\n");
59
60         ReleaseResponse(); // release leftover
61     //alloc new sp_response
62         sp_response = at_response_new();
63
64         ur = tcore_pending_ref_user_request(p);
65         metainfo = (struct ATReqMetaInfo*)tcore_user_request_ref_metainfo(ur,&info_len);
66
67         if ((metainfo->type == SINGLELINE)||(metainfo->type == MULTILINE))      {
68                 //cp rsp prefix
69                 s_responsePrefix = strdup(metainfo->responsePrefix);
70                 dbg("duplicating responsePrefix : %s\n", s_responsePrefix);
71         }
72         else {
73                 s_responsePrefix = NULL;
74         }
75
76         //set atcmd type into s_type
77         s_type = metainfo->type;
78
79         if (result == FALSE) {
80                 /* Fail */
81                 dbg("SEND FAIL");
82         }
83         else {
84                 dbg("SEND OK");
85         }
86 }
87
88
89 static TReturn _pdp_device_control(gboolean flag, unsigned int context_id)
90 {
91         int size = 0;
92         int fd = 0;
93         char buf[32];
94         char *control = NULL;
95
96         if (context_id > 3)
97                 return TCORE_RETURN_EINVAL;
98
99         if (flag)
100                 control = "/sys/class/net/svnet0/pdp/activate";
101         else
102                 control = "/sys/class/net/svnet0/pdp/deactivate";
103
104         fd = open(control, O_WRONLY);
105         if (fd < 0) {
106                 return TCORE_RETURN_FAILURE;
107         }
108
109         snprintf(buf, sizeof(buf), "%d", context_id);
110         size = write(fd, buf, strlen(buf));
111
112         close(fd);
113         return TCORE_RETURN_SUCCESS;
114 }
115
116 static void on_event_ps_ipconfiguration(CoreObject *o, const void *event_info, void *user_data)
117 {
118         /* Parsing the response line and map into noti. */
119         CoreObject *ps_context = (CoreObject *)user_data;
120         unsigned int pdpContextCnt, cid = tcore_context_get_id(ps_context);
121         struct ATLine *p_cur = NULL;
122         const struct ATResponse *p_response = event_info;
123         int err, ret, p_cid=0, d_comp = -1, h_comp = -1;
124         struct tnoti_ps_pdp_ipconfiguration noti;
125         char devname[10] = {0,};
126         char addr_buf[5][20];
127         char *pdp_type = NULL, *apn = NULL;
128         char *line = NULL, *ip = NULL, *gateway = NULL;//, *netmask = NULL;
129
130         /* count the PDP contexts */
131         for (pdpContextCnt = 0, p_cur = p_response->p_intermediates
132                         ; p_cur != NULL
133                         ; p_cur = p_cur->p_next) {
134                 pdpContextCnt++;
135         }
136
137         dbg("Total number of PDP contexts : %d",pdpContextCnt);
138
139         if(pdpContextCnt == 0)
140                 return;
141
142         for (p_cur = p_response->p_intermediates
143                         ; p_cur != NULL
144                         ; p_cur = p_cur->p_next) {
145                 line = p_response->p_intermediates->line;
146
147                 err = at_tok_start(&line);
148                 err = at_tok_nextint(&line,&p_cid);
149                 dbg("cid: %d", p_cid);
150
151                 /* Send IP Configuration noti only on the requested CID. */
152                 if (p_cid && (cid == (unsigned int)p_cid))      {
153                         err = at_tok_nextstr(&line,&pdp_type);
154                         dbg("PDP type: %s", pdp_type);
155
156                         if (pdp_type!=NULL)     {
157                                 err = at_tok_nextstr(&line,&apn);
158                                 dbg("APN: %s", apn);
159                         }
160                         if (apn !=NULL) {
161                                 err = at_tok_nextstr(&line,&ip);
162                                 dbg("IP address: %s", ip);
163                         }
164                         if (ip !=NULL) {
165                                 err = at_tok_nextint(&line,&d_comp);
166                                 dbg("d_comp: %d", d_comp);
167                         }
168                         if (d_comp != -1) {
169                                 err = at_tok_nextint(&line,&h_comp);
170                                 dbg("h_comp: %d", h_comp);
171                         }
172
173                         memset(&noti, 0, sizeof(struct tnoti_ps_pdp_ipconfiguration));
174
175                         noti.context_id = cid;
176                         noti.err = 0;
177
178                         /* Just use AF_INET here. */
179                         ret = inet_pton(AF_INET, ip, &noti.ip_address);
180                         if (ret < 1) {
181                                 dbg("inet_pton() failed.");
182                                 return;
183                         }
184
185                         snprintf(addr_buf[0], 20, "%d.%d.%d.%d", noti.ip_address[0], noti.ip_address[1],
186                                         noti.ip_address[2], noti.ip_address[3]);
187                         ip = addr_buf[0];
188                         dbg("ip = [%s]", ip);
189
190                         noti.primary_dns[0] = 8;
191                         noti.primary_dns[1] = 8;
192                         noti.primary_dns[2] = 8;
193                         noti.primary_dns[3] = 8;
194                         dbg("primary_dns = [8.8.8.8] Public DNS server.");
195
196                         noti.secondary_dns[0] = 8;
197                         noti.secondary_dns[1] = 8;
198                         noti.secondary_dns[2] = 4;
199                         noti.secondary_dns[3] = 4;
200                         dbg("secondary_dns = [8.8.4.4] Public DNS server.");
201
202                         memcpy(&noti.gateway, &noti.ip_address, 4);
203                         noti.gateway[3] = 1;
204                         snprintf(addr_buf[3], 20, "%d.%d.%d.%d", noti.gateway[0], noti.gateway[1], noti.gateway[2],
205                                         noti.gateway[3]);
206                         gateway = addr_buf[3];
207                         dbg("gateway = [%s]", gateway);
208
209                         /* FIX ME: use static netmask. */
210                         noti.subnet_mask[0] = 255;
211                         noti.subnet_mask[1] = 255;
212                         noti.subnet_mask[2] = 255;
213                         noti.subnet_mask[3] = 0;
214                         dbg("subnet_mask = [255.255.255.0]");
215
216                         if (_pdp_device_control(TRUE, cid) != TCORE_RETURN_SUCCESS) {
217                                 dbg("_pdp_device_control() failed. errno=%d", errno);
218                         }
219
220                         snprintf(devname, 10, "pdp%d", cid - 1);
221                         memcpy(noti.devname, devname, 10);
222                         dbg("devname = [%s]", devname);
223
224                         if (tcore_util_netif_up(devname) != TCORE_RETURN_SUCCESS) {
225                                 dbg("util_netif_up() failed. errno=%d", errno);
226                         }
227                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_PS_PDP_IPCONFIGURATION,
228                                         sizeof(struct tnoti_ps_pdp_ipconfiguration), &noti);
229                 }
230                 else
231                         dbg("No matched response with CID: %d",cid);
232         }
233 }
234
235 static void on_response_get_ipconfiguration(TcorePending *pending, int data_len, const void *data, void *user_data)
236 {
237         struct ATLine *p_cur;
238         CoreObject *ps_context = (CoreObject *)user_data;
239         char *line = NULL;
240
241         printResponse();
242
243         if (sp_response->success > 0) {
244                 dbg("RESPONSE OK");
245
246                 for (p_cur = sp_response->p_intermediates
247                                 ; p_cur != NULL
248                                 ; p_cur = p_cur->p_next) {
249                         line = sp_response->p_intermediates->line;
250                         dbg("%s\n", line);
251                 }
252
253                 dbg("Call on_ipc_event_ps_ipconfiguration");
254                 on_event_ps_ipconfiguration(tcore_pending_ref_core_object(pending), sp_response, ps_context);
255         }
256         else {
257                 dbg("RESPONSE NOK");
258         }
259
260         ReleaseResponse();
261 }
262
263 static void on_response_ps_attached(TcorePending *p, int data_len, const void *data, void *user_data)
264 {
265         TcorePlugin *pl = NULL;
266         TcoreHal *h = NULL;
267         TcorePending *pending = NULL;
268         CoreObject *o = tcore_pending_ref_core_object(p);
269         CoreObject *ps_context = (CoreObject *)user_data;
270         UserRequest *ur;
271
272         char* cmd_str = NULL;
273         struct ATReqMetaInfo metainfo;
274         int info_len =0;
275         char* line = NULL;
276
277         printResponse();
278
279         if (sp_response->success > 0) {
280                 dbg("RESPONSE OK");
281                 line = sp_response->p_intermediates->line;
282                 dbg("on_response_ps_attached: %s", line);
283
284                 ur = tcore_user_request_new(NULL, NULL);
285                 memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
286                 memcpy(metainfo.responsePrefix,"+CGDCONT:",strlen("+CGDCONT:"));
287                 metainfo.type = MULTILINE;
288                 info_len = sizeof(struct ATReqMetaInfo);
289
290                 tcore_user_request_set_metainfo(ur, info_len, &metainfo);
291
292                 dbg(" Send: AT+CGDCONT?\r ");
293                 cmd_str = g_strdup("AT+CGDCONT?\r");
294
295                 pl = tcore_object_ref_plugin(o);
296                 h = tcore_object_get_hal(o);
297                 pending = tcore_pending_new(o, ID_RESERVED_AT);
298                 tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
299                 free(cmd_str);
300
301                 tcore_pending_set_timeout(pending, 0);
302                 tcore_pending_set_response_callback(pending, on_response_get_ipconfiguration, ps_context);
303                 tcore_pending_link_user_request(pending, ur);
304                 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
305                 tcore_pending_set_send_callback(pending, on_confirmation_ps_message_send, NULL);
306                 tcore_hal_send_request(h, pending);
307         }
308         else {
309                 dbg("RESPONSE NOK");
310         }
311
312         ReleaseResponse();
313 }
314
315 static void on_response_active_set(TcorePending *p, int data_len, const void *data, void *user_data)
316 {
317         TcorePlugin *pl = NULL;
318         TcoreHal *h = NULL;
319         TcorePending *pending = NULL;
320         CoreObject *o = tcore_pending_ref_core_object(p);
321         CoreObject *ps_context = (CoreObject *)user_data;
322         UserRequest *ur;
323
324         char* cmd_str = NULL;
325         struct ATReqMetaInfo metainfo;
326         int info_len =0;
327
328         printResponse();
329
330         if (sp_response->success > 0) {
331                 dbg("RESPONSE OK");
332
333                 ur = tcore_user_request_new(NULL, NULL);
334                 memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
335                 metainfo.type = SINGLELINE;
336                 info_len = sizeof(struct ATReqMetaInfo);
337
338                 tcore_user_request_set_metainfo(ur, info_len, &metainfo);
339
340                 dbg(" Send: ATD*99***1#\r ");
341                 cmd_str = g_strdup("ATD*99***1#\r");
342
343                 pl = tcore_object_ref_plugin(o);
344                 h = tcore_object_get_hal(o);
345                 pending = tcore_pending_new(o, ID_RESERVED_AT);
346
347                 tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
348                 free(cmd_str);
349
350                 tcore_pending_set_timeout(pending, 0);
351                 tcore_pending_set_response_callback(pending, on_response_ps_attached, ps_context);
352                 tcore_pending_link_user_request(pending, ur);
353                 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
354                 tcore_pending_set_send_callback(pending, on_confirmation_ps_message_send, NULL);
355                 tcore_hal_send_request(h, pending);
356         }
357         else {
358                 dbg("RESPONSE NOK");
359                 tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
360         }
361
362         ReleaseResponse();
363 }
364
365 static void on_response_deactive_set(TcorePending *p, int data_len, const void *data, void *user_data)
366 {
367         printResponse();
368
369         if (sp_response->success > 0) {
370                 dbg("RESPONSE OK");
371         }
372         else {
373                 dbg("RESPONSE NOK");
374         }
375
376         ReleaseResponse();
377 }
378
379 static TReturn activate_ps_context(CoreObject *o, CoreObject *ps_context, void* user_data)
380 {
381         TcorePlugin *p = NULL;
382         TcoreHal *h = NULL;
383         TcorePending *pending = NULL;
384         UserRequest *ur;
385
386         unsigned int cid;
387         char* cmd_str = NULL;
388         struct ATReqMetaInfo metainfo;
389         int info_len =0;
390
391         if ( !o )
392                 return TCORE_RETURN_FAILURE;
393
394         p = tcore_object_ref_plugin(o);
395         h = tcore_object_get_hal(o);
396
397
398         ur = tcore_user_request_new(NULL, NULL);
399         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
400         metainfo.type = NO_RESULT;
401         info_len = sizeof(struct ATReqMetaInfo);
402
403         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
404
405         cid = tcore_context_get_id(ps_context);
406
407         dbg("Example: AT+CGACT=1,0");
408         cmd_str = g_strdup_printf("%s=%d,%d%s","AT+CGACT", 1, cid, "\r");
409
410         pending = tcore_pending_new(o, ID_RESERVED_AT);
411         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
412         free(cmd_str);
413
414         tcore_pending_set_timeout(pending, 0);
415         tcore_pending_set_response_callback(pending, on_response_active_set, ps_context);
416         tcore_pending_link_user_request(pending, ur);
417         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
418         tcore_pending_set_send_callback(pending, on_confirmation_ps_message_send, NULL);
419         tcore_hal_send_request(h, pending);
420
421         return TRUE;
422 }
423
424 static void on_response_define_pdp(TcorePending *p, int data_len, const void *data, void *user_data)
425 {
426         //CoreObject *ps_context = user_data;
427
428         printResponse();
429
430         if (sp_response->success > 0) {
431                 dbg("RESPONSE OK");
432                 //pdp_active_set(tcore_pending_ref_core_object(p), ps_context);
433         }
434         else {
435                 dbg("RESPONSE NOK");
436                 tcore_context_set_state(tcore_pending_ref_core_object(p), CONTEXT_STATE_DEACTIVATED);
437         }
438
439         ReleaseResponse();
440 }
441
442 static TReturn define_ps_context(CoreObject *o, CoreObject *ps_context, void *user_data)
443 {
444         TcorePlugin *p = NULL;
445         TcoreHal *h = NULL;
446         TcorePending *pending = NULL;
447         UserRequest *ur;
448
449         char *apn=NULL, *addr=NULL;
450
451         unsigned int cid;
452         enum co_context_type pdp_type;
453         enum co_context_d_comp d_comp;
454         enum co_context_h_comp h_comp;
455         char *cmd_str = NULL;
456         struct ATReqMetaInfo metainfo;
457         int info_len =0;
458
459         if ( !o )
460                 return TCORE_RETURN_FAILURE;
461
462         p = tcore_object_ref_plugin(o);
463         h = tcore_object_get_hal(o);
464     ur = tcore_user_request_new(NULL, NULL);
465         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
466         metainfo.type = NO_RESULT;
467         info_len = sizeof(struct ATReqMetaInfo);
468
469         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
470
471         cid = tcore_context_get_id(ps_context);
472         pdp_type = tcore_context_get_type(ps_context);
473         d_comp = tcore_context_get_data_compression(ps_context);
474         h_comp = tcore_context_get_header_compression(ps_context);
475
476         dbg("Example: AT+CGDCONT=1,\"IP\",\"www.example.co.kr\",,0,0");
477         cmd_str = g_strdup_printf("AT+CGDCONT=%d,\"%d\",\"%s\",%s,%d,%d%s",
478                         cid, pdp_type, apn, addr, d_comp, h_comp, "\r");
479
480         pending = tcore_pending_new(o, ID_RESERVED_AT);
481         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
482         free(cmd_str);
483
484         tcore_pending_set_timeout(pending, 0);
485         tcore_pending_set_response_callback(pending, on_response_define_pdp, ps_context);
486         tcore_pending_link_user_request(pending, ur);
487         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
488         tcore_pending_set_send_callback(pending, on_confirmation_ps_message_send, NULL);
489         tcore_hal_send_request(h, pending);
490
491         return TCORE_RETURN_SUCCESS;
492 }
493
494 static TReturn deactivate_ps_context(CoreObject *o, CoreObject *ps_context, void *user_data)
495 {
496         TcorePlugin *p = NULL;
497         TcoreHal *h = NULL;
498         TcorePending *pending = NULL;
499         UserRequest *ur;
500
501         unsigned int cid;
502         char* cmd_str = NULL;
503         struct ATReqMetaInfo metainfo;
504         int info_len =0;
505
506         if ( !o )
507                 return TCORE_RETURN_FAILURE;
508
509         p = tcore_object_ref_plugin(o);
510         h = tcore_object_get_hal(o);
511         ur = tcore_user_request_new(NULL, NULL);
512
513         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
514         metainfo.type = NO_RESULT;
515         info_len = sizeof(struct ATReqMetaInfo);
516
517         cid = tcore_context_get_id(ps_context);
518
519         dbg("Example: AT+CGACT=0,1");
520         cmd_str = g_strdup_printf("%s=%d,%d%s","AT+CGACT", 0, cid, "\r");
521
522         pending = tcore_pending_new(o, ID_RESERVED_AT);
523         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
524         free(cmd_str);
525
526         tcore_pending_set_timeout(pending, 0);
527         tcore_pending_set_response_callback(pending, on_response_deactive_set, ps_context);
528         tcore_pending_link_user_request(pending, ur);
529         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
530         tcore_pending_set_send_callback(pending, on_confirmation_ps_message_send, NULL);
531         tcore_hal_send_request(h, pending);
532
533         return TCORE_RETURN_SUCCESS;
534 }
535
536 static struct tcore_ps_operations ps_ops =
537 {
538         .define_context = define_ps_context,
539         .activate_context = activate_ps_context,
540         .deactivate_context = deactivate_ps_context
541 };
542
543 gboolean s_ps_init(TcorePlugin *p, TcoreHal *h)
544 {
545         CoreObject *o;
546         GQueue *work_queue;
547
548         o = tcore_ps_new(p, "umts_ps", &ps_ops, h);
549         if (!o)
550                 return FALSE;
551
552         work_queue = g_queue_new();
553         tcore_object_link_user_data(o, work_queue);
554
555         return TRUE;
556 }
557
558 void s_ps_exit(TcorePlugin *p)
559 {
560         CoreObject *o;
561         GQueue *work_queue;
562
563         o = tcore_plugin_ref_core_object(p, "umts_ps");
564         if (!o)
565                 return;
566
567         work_queue = tcore_object_ref_user_data(o);
568         if (work_queue)
569                 g_queue_free(work_queue);
570
571         tcore_ps_free(o);
572 }