tizen 2.3.1 release
[framework/telephony/libtcore.git] / src / co_ps.c
1 /*
2  * libtcore
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Ja-young Gu <jygu@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
25 #include <glib.h>
26
27 #include "tcore.h"
28 #include "plugin.h"
29 #include "user_request.h"
30 #include "co_ps.h"
31
32 struct p_callid_type{
33         unsigned int cid;
34         gboolean active;
35         gboolean connected;
36         gchar *apn;
37         GSList *contexts;
38 };
39
40 struct private_object_data {
41         struct tcore_ps_operations *ops;
42
43         gboolean online;
44         gint num_of_pdn;
45
46         /* 1 ~ UMTS_PS_MAX_CID */
47         struct p_callid_type cid[PS_MAX_CID + 1];
48         //CoreObject *cid[PS_MAX_CID + 1];
49
50         GSList *context_list;
51 };
52
53 static TReturn _dispatcher(CoreObject *o, UserRequest *ur)
54 {
55         enum tcore_request_command command;
56         struct private_object_data *po = NULL;
57
58         if (!o || !ur)
59                 return TCORE_RETURN_EINVAL;
60
61         po = tcore_object_ref_object(o);
62         if (!po || !po->ops)
63                 return TCORE_RETURN_ENOSYS;
64
65         command = tcore_user_request_get_command(ur);
66         switch (command) {
67                 default:
68                         break;
69         }
70
71         return TCORE_RETURN_SUCCESS;
72 }
73
74 static void _clone_hook(CoreObject *src, CoreObject *dest)
75 {
76         struct private_object_data *src_po = NULL;
77         struct private_object_data *dest_po = NULL;
78
79         if (!src || !dest)
80                 return;
81
82         dest_po = calloc(1, sizeof(struct private_object_data));
83         if (!dest_po) {
84                 tcore_object_link_object(dest, NULL);
85                 return;
86         }
87
88         src_po = tcore_object_ref_object(src);
89         dest_po->ops = src_po->ops;
90
91         tcore_object_link_object(dest, dest_po);
92 }
93
94 static void _free_hook(CoreObject *o)
95 {
96         struct private_object_data *po = NULL;
97         GSList *list;
98
99         po = tcore_object_ref_object(o);
100         if (!po)
101                 return;
102
103         if (po->context_list) {
104                 for (list = po->context_list; list; list = list->next) {
105                         if (list->data)
106                                 free(list->data);
107
108                         list->data = NULL;
109                 }
110
111                 g_slist_free(po->context_list);
112                 po->context_list = NULL;
113         }
114
115         free(po);
116         tcore_object_link_object(o, NULL);
117 }
118
119 static gboolean _ps_is_active_context(CoreObject *o, CoreObject *ps_context)
120 {
121         GSList *contexts = NULL;
122         CoreObject *s_context = NULL;
123
124         int idx_cid = 0;
125         struct private_object_data *po = NULL;
126
127         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, FALSE);
128
129         po = tcore_object_ref_object(o);
130
131         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
132                 if (po->cid[idx_cid].cid == 0)
133                         continue;
134
135                 contexts = po->cid[idx_cid].contexts;
136                 if (!contexts)
137                         continue;
138
139                 while (contexts) {
140                         s_context = contexts->data;
141                         if (!s_context) {
142                                 contexts = contexts->next;
143                                 continue;
144                         }
145
146                         if (ps_context == s_context) {
147                                 dbg("find contexts(%p) in cid(%d)", ps_context, idx_cid);
148                                 return TRUE;
149                         }
150
151                         contexts = contexts->next;
152                 }
153         }
154
155         dbg("cannot find contexts(%p) ", ps_context);
156
157         return FALSE;
158 }
159
160 static gboolean _ps_is_duplicated_apn(CoreObject *o, CoreObject *ps_context)
161 {
162         GSList *contexts = NULL;
163         CoreObject *s_context = NULL;
164         gchar *t_apn = NULL, *s_apn = NULL;
165
166         int idx_cid = 0;
167         struct private_object_data *po = NULL;
168
169         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, FALSE);
170
171         po = tcore_object_ref_object(o);
172         t_apn = tcore_context_get_apn(ps_context);
173
174         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
175                 if (po->cid[idx_cid].cid == 0)
176                         continue;
177
178                 contexts = po->cid[idx_cid].contexts;
179                 if (!contexts)
180                         continue;
181
182                 while (contexts) {
183                         s_context = contexts->data;
184                         if (!s_context) {
185                                 contexts = contexts->next;
186                                 continue;
187                         }
188
189                         if (ps_context == s_context) {
190                                 contexts = contexts->next;
191                                 continue;
192                         }
193
194                         s_apn = tcore_context_get_apn(s_context);
195                         if (g_strcmp0(t_apn, s_apn) == 0) {
196                                 dbg("target and source context have same APN");
197                                 tcore_context_cp_service_info(ps_context, s_context);
198                                 g_free(t_apn);
199                                 g_free(s_apn);
200                                 return TRUE;
201                         }
202                         g_free (s_apn);
203
204                         contexts = contexts->next;
205                 }
206         }
207
208         g_free(t_apn);
209         return FALSE;
210 }
211
212 static void _deactivate_context (gpointer context, gpointer user_data)
213 {
214         if (!context || !user_data)
215                 return;
216
217         tcore_ps_deactivate_context(user_data, context, NULL);
218 }
219
220 CoreObject *tcore_ps_new(TcorePlugin *p, const char *name,
221                 struct tcore_ps_operations *ops, TcoreHal *hal)
222 {
223         CoreObject *o = NULL;
224         struct private_object_data *po = NULL;
225
226         if (!p)
227                 return NULL;
228
229         o = tcore_object_new(p, name, hal);
230         if (!o)
231                 return NULL;
232
233         po = calloc(1, sizeof(struct private_object_data));
234         if (!po) {
235                 tcore_object_free(o);
236                 return NULL;
237         }
238
239         po->ops = ops;
240
241         tcore_object_set_type(o, CORE_OBJECT_TYPE_PS);
242         tcore_object_link_object(o, po);
243         tcore_object_set_free_hook(o, _free_hook);
244         tcore_object_set_clone_hook(o, _clone_hook);
245         tcore_object_set_dispatcher(o, _dispatcher);
246
247         return o;
248 }
249
250 void tcore_ps_free(CoreObject *o)
251 {
252         CORE_OBJECT_CHECK(o, CORE_OBJECT_TYPE_PS);
253         tcore_object_free(o);
254 }
255
256 void tcore_ps_set_ops(CoreObject *o, struct tcore_ps_operations *ops)
257 {
258         struct private_object_data *po = NULL;
259
260         CORE_OBJECT_CHECK(o, CORE_OBJECT_TYPE_PS);
261
262         po = (struct private_object_data *)tcore_object_ref_object(o);
263         if (!po) {
264                 return;
265         }
266
267         po->ops = ops;
268 }
269
270 TReturn tcore_ps_add_context(CoreObject *o, CoreObject *ctx_o)
271 {
272         struct private_object_data *po = NULL;
273
274         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
275         CORE_OBJECT_CHECK_RETURN(ctx_o, CORE_OBJECT_TYPE_PS_CONTEXT, TCORE_RETURN_EINVAL);
276
277         po = tcore_object_ref_object(o);
278         if (!po)
279                 return TCORE_RETURN_EINVAL;
280
281         po->context_list = g_slist_insert(po->context_list, ctx_o, 0);
282
283         return TCORE_RETURN_SUCCESS;
284 }
285
286 TReturn tcore_ps_remove_context(CoreObject *o, CoreObject *ctx_o)
287 {
288         struct private_object_data *po = NULL;
289
290         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
291         CORE_OBJECT_CHECK_RETURN(ctx_o, CORE_OBJECT_TYPE_PS_CONTEXT, TCORE_RETURN_EINVAL);
292
293         po = tcore_object_ref_object(o);
294         if (!po)
295                 return TCORE_RETURN_EINVAL;
296
297         tcore_ps_clear_context_id(o, ctx_o);
298         po->context_list = g_slist_remove(po->context_list, ctx_o);
299
300         return TCORE_RETURN_SUCCESS;
301 }
302
303 TReturn tcore_ps_set_online(CoreObject *o, gboolean state)
304 {
305         struct private_object_data *po = NULL;
306
307         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
308
309         po = tcore_object_ref_object(o);
310         if (!po)
311                 return TCORE_RETURN_EINVAL;
312
313         po->online = state;
314         dbg("ps status = %d", po->online);
315
316         return TCORE_RETURN_SUCCESS;
317 }
318
319 TReturn tcore_ps_set_num_of_pdn(CoreObject *o, gint numbers)
320 {
321         struct private_object_data *po = NULL;
322
323         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
324
325         po = tcore_object_ref_object(o);
326         if (!po)
327                 return TCORE_RETURN_EINVAL;
328
329         po->num_of_pdn = numbers;
330         dbg("ps num of pdn = %d", po->num_of_pdn);
331
332         return TCORE_RETURN_SUCCESS;
333 }
334
335 unsigned int tcore_ps_get_num_of_pdn(CoreObject *o)
336 {
337         struct private_object_data *po = NULL;
338
339         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, 0);
340
341         po = tcore_object_ref_object(o);
342         if (!po)
343                 return 0;
344
345         return po->num_of_pdn;
346 }
347
348 unsigned int tcore_ps_set_cid_active(CoreObject *o, unsigned int cid, unsigned int enable)
349 {
350         int idx_cid = 0;
351         struct private_object_data *po = NULL;
352
353         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, 0);
354         if(cid == 0){
355                 return 0;
356         }
357
358         po = tcore_object_ref_object(o);
359         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
360                 if (po->cid[idx_cid].cid == cid){
361                         po->cid[idx_cid].active = enable;
362                         return 1;
363                 }
364         }
365
366         return 0;
367 }
368
369 unsigned int tcore_ps_get_cid_active(CoreObject *o, unsigned int cid)
370 {
371         int idx_cid = 0;
372         struct private_object_data *po = NULL;
373
374         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, 0);
375         if(cid == 0){
376                 return 0;
377         }
378
379         po = tcore_object_ref_object(o);
380         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
381                 if (po->cid[idx_cid].cid == cid){
382                         return po->cid[idx_cid].active;
383                 }
384         }
385
386         return 0;
387 }
388
389 GSList* tcore_ps_get_active_cids(CoreObject *o)
390 {
391         int idx_cid = 0;
392         GSList *active_list = NULL;
393         struct private_object_data *po = NULL;
394
395         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, NULL);
396
397         po = tcore_object_ref_object(o);
398
399         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
400                 if (po->cid[idx_cid].active){
401                         active_list = g_slist_append(active_list, &po->cid[idx_cid].cid);
402                 }
403         }
404
405         return active_list;
406 }
407
408 unsigned int tcore_ps_set_cid_connected(CoreObject *o, unsigned int cid, unsigned int connected)
409 {
410         int idx_cid = 0;
411         struct private_object_data *po = NULL;
412
413         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, 0);
414         if(cid == 0){
415                 return 0;
416         }
417
418         po = tcore_object_ref_object(o);
419         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
420                 if (po->cid[idx_cid].cid == cid){
421                         po->cid[idx_cid].connected = connected;
422                         return 1;
423                 }
424         }
425
426         return 0;
427 }
428
429 unsigned int tcore_ps_get_cid_connected(CoreObject *o, unsigned int cid)
430 {
431         int idx_cid = 0;
432         struct private_object_data *po = NULL;
433
434         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, 0);
435         if(cid == 0){
436                 return 0;
437         }
438
439         po = tcore_object_ref_object(o);
440         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
441                 if (po->cid[idx_cid].cid == cid){
442                         return po->cid[idx_cid].connected;
443                 }
444         }
445
446         return 0;
447 }
448
449 GSList* tcore_ps_get_connected_cids(CoreObject *o)
450 {
451         int idx_cid = 0;
452         GSList *active_list = NULL;
453         struct private_object_data *po = NULL;
454
455         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, NULL);
456
457         po = tcore_object_ref_object(o);
458
459         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++) {
460                 if (po->cid[idx_cid].connected){
461                         active_list = g_slist_append(active_list, &po->cid[idx_cid].cid);
462                 }
463         }
464
465         return active_list;
466 }
467
468 unsigned int tcore_ps_is_active_apn(CoreObject *o, const char* apn)
469 {
470         int idx_cid = 0;
471         struct private_object_data *po = NULL;
472
473         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, 0);
474
475         po = tcore_object_ref_object(o);
476
477         for (idx_cid = 1; idx_cid <= po->num_of_pdn; idx_cid++){
478                 if (po->cid[idx_cid].cid == 0)
479                         continue;
480
481                 if (g_strcmp0((const char*)po->cid[idx_cid].apn, apn) == 0 && po->cid[idx_cid].active) {
482                         return 1;
483                 }
484         }
485
486         return 0;
487 }
488
489 CoreObject *tcore_ps_ref_context_by_role(CoreObject *o, enum co_context_role role)
490 {
491         struct private_object_data *po = NULL;
492         GSList *list;
493         CoreObject *pdp_o;
494         TcorePlugin *p;
495
496         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, NULL);
497
498         po = tcore_object_ref_object(o);
499         if (!po)
500                 return NULL;
501
502         p = tcore_object_ref_plugin(o);
503         if (!p)
504                 return NULL;
505
506         if (po->context_list) {
507                 for (list = po->context_list; list; list = list->next) {
508                         if (!list->data)
509                                 continue;
510
511                         pdp_o = list->data;
512                         if (!pdp_o)
513                                 continue;
514
515                         if (tcore_object_get_type(pdp_o) != CORE_OBJECT_TYPE_PS_CONTEXT)
516                                 continue;
517
518                         if (tcore_context_get_role(pdp_o) == role)
519                                 return pdp_o;
520                 }
521         }
522
523         return NULL;
524 }
525
526 GSList *tcore_ps_ref_context_by_id(CoreObject *o, unsigned int id)
527 {
528         struct private_object_data *po = NULL;
529
530         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, NULL);
531
532         po = tcore_object_ref_object(o);
533         if (!po)
534                 return NULL;
535
536         if (id == 0 || id > (unsigned int)po->num_of_pdn)
537                 return NULL;
538
539         if (po->cid[id].cid != id)
540                 return NULL;
541
542         return po->cid[id].contexts;
543 }
544
545 gboolean tcore_ps_any_context_activating_activated(CoreObject *o, int * state)
546 {
547         struct private_object_data *po = NULL;
548         CoreObject *pdp_o;
549         gboolean ret = FALSE;
550         GSList *list = NULL;
551         enum co_context_state context_state = CONTEXT_STATE_DEACTIVATED;
552
553         po = tcore_object_ref_object(o);
554         if (!po)
555                 return ret;
556
557         if (po->context_list) {
558                 for (list = po->context_list; list; list = list->next) {
559                         if (!list->data)
560                                 continue;
561
562                         pdp_o = list->data;
563
564                         if (tcore_object_get_type(pdp_o) != CORE_OBJECT_TYPE_PS_CONTEXT)
565                                 continue;
566
567                         context_state = tcore_context_get_state(pdp_o);
568
569                         if(CONTEXT_STATE_ACTIVATED == context_state) {
570                                 *state = CONTEXT_STATE_ACTIVATED;
571                                 return  TRUE;
572                         }
573                         else if (CONTEXT_STATE_ACTIVATING == context_state){
574                                 *state = CONTEXT_STATE_ACTIVATING;
575                                 ret = TRUE;
576                                 continue;
577                         }
578                         else if (CONTEXT_STATE_DEACTIVATING == context_state){
579                                 *state = CONTEXT_STATE_DEACTIVATING;
580                                 ret = TRUE;
581                                 continue;
582                         }
583                 }
584         }
585         return ret;
586 }
587
588
589 TReturn tcore_ps_assign_context_id(CoreObject *o, CoreObject *context, unsigned char cid)
590 {
591         struct private_object_data *po = NULL;
592         unsigned char idx;
593
594         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
595         CORE_OBJECT_CHECK_RETURN(context, CORE_OBJECT_TYPE_PS_CONTEXT, TCORE_RETURN_EINVAL);
596
597         po = tcore_object_ref_object(o);
598         if (!po)
599                 return TCORE_RETURN_EINVAL;
600
601         if (cid == 0) {
602                 /* Automatic assign */
603                 for (idx = 1; idx <= po->num_of_pdn; idx++) {
604                         if (po->cid[idx].cid == 0) {
605                                 po->cid[idx].cid = idx;
606                                 po->cid[idx].contexts = g_slist_append(po->cid[idx].contexts, context);
607                                 po->cid[idx].apn = tcore_context_get_apn(context);
608                                 dbg("assign contexts(%p) in cid(%d), apn(%s)", context, idx, po->cid[idx].apn);
609                                 return tcore_context_set_id(context, idx);
610                         }
611                         else {
612                                 dbg("cid[%d] is not null", idx);
613                         }
614                 }
615
616                 dbg("can't find empty cid");
617         }
618         else {
619                 /* Manual assign */
620                 if (po->cid[cid].cid == cid) {
621                         po->cid[cid].contexts = g_slist_append(po->cid[cid].contexts, context);
622                         return tcore_context_set_id(context, cid);
623                 }
624                 else {
625                         dbg("cid[%d] is not null", cid);
626                 }
627         }
628
629         return TCORE_RETURN_PS_CID_ERROR;
630 }
631
632 TReturn tcore_ps_clear_context_id(CoreObject *o, CoreObject *context)
633 {
634         struct private_object_data *po = NULL;
635         unsigned char i = 0, cnt = 0;
636
637         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
638         CORE_OBJECT_CHECK_RETURN(context, CORE_OBJECT_TYPE_PS_CONTEXT, TCORE_RETURN_EINVAL);
639
640         po = tcore_object_ref_object(o);
641         if (!po)
642                 return TCORE_RETURN_EINVAL;
643
644         i = tcore_context_get_id(context);
645         if (i == 0) {
646                 return TCORE_RETURN_PS_CID_ERROR;
647         }
648
649         if (i > po->num_of_pdn)
650                 return TCORE_RETURN_PS_CID_ERROR;
651
652         po->cid[i].contexts = g_slist_remove(po->cid[i].contexts, context);
653         cnt = g_slist_length(po->cid[i].contexts);
654         if (cnt <= 0){
655                 po->cid[i].cid = 0;
656                 po->cid[i].active = FALSE;
657                 po->cid[i].connected = FALSE;
658                 g_free(po->cid[i].apn);
659                 po->cid[i].apn = NULL;
660         }
661
662         return tcore_context_set_id(context, 0);
663 }
664
665 TReturn tcore_ps_define_context(CoreObject *o, CoreObject *ps_context, void *user_data)
666 {
667         int rv;
668         struct private_object_data *po = NULL;
669
670         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
671
672         po = tcore_object_ref_object(o);
673         if (!po)
674                 return TCORE_RETURN_EINVAL;
675
676         if (!ps_context)
677                 return TCORE_RETURN_EINVAL;
678
679         rv = _ps_is_active_context(o, ps_context);
680         if (rv)
681                 return TCORE_RETURN_SUCCESS;
682
683         rv = _ps_is_duplicated_apn(o, ps_context);
684         if (rv) {
685                 unsigned char cid = 0;
686                 cid = tcore_context_get_id(ps_context);
687                 po->cid[cid].contexts = g_slist_append(po->cid[cid].contexts, ps_context);
688                 return TCORE_RETURN_SUCCESS;
689         }
690
691         if (tcore_context_get_id(ps_context) == 0) {
692                 if (tcore_ps_assign_context_id(o, ps_context, 0) != TCORE_RETURN_SUCCESS)
693                         return TCORE_RETURN_PS_CID_ERROR;
694         }
695
696         dbg("contexts(%p), cid = %d", ps_context, tcore_context_get_id(ps_context));
697
698         return po->ops->define_context(o, ps_context, user_data);
699 }
700
701 TReturn tcore_ps_activate_context(CoreObject *o, CoreObject *ps_context, void *user_data)
702 {
703         int rv;
704         struct private_object_data *po = NULL;
705         enum co_context_state context_state = CONTEXT_STATE_DEACTIVATED;
706
707         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
708
709         po = tcore_object_ref_object(o);
710         if (!po)
711                 return TCORE_RETURN_EINVAL;
712
713         if (!po->online) {
714                 dbg("ps network is not online !");
715                 return TCORE_RETURN_PS_NETWORK_NOT_READY;
716         }
717
718         if (!ps_context)
719                 return TCORE_RETURN_EINVAL;
720
721         rv = _ps_is_active_context(o, ps_context);
722         if (!rv)
723         {
724                 dbg("it is not defined context");
725                 return TCORE_RETURN_EINVAL;
726         }
727
728         rv = _ps_is_duplicated_apn(o, ps_context);
729         if (rv) {
730                 dbg("context activation is already requested for the same apn(%s)",
731                         tcore_context_get_apn(ps_context));
732                 return TCORE_RETURN_SUCCESS;
733         }
734
735         context_state = tcore_context_get_state(ps_context);
736
737         if (context_state == CONTEXT_STATE_ACTIVATED){
738                 dbg("Context state : CONTEXT_STATE_ACTIVATED");
739                 return TCORE_RETURN_SUCCESS;
740         }
741         else if (context_state == CONTEXT_STATE_ACTIVATING){
742                 dbg("Context state : CONTEXT_STATE_ACTIVATING");
743                 return TCORE_RETURN_SUCCESS;
744         }
745         else if (context_state == CONTEXT_STATE_DEACTIVATING){
746                 dbg("Context state : CONTEXT_STATE_DEACTIVATING");
747                 return TCORE_RETURN_PS_DEACTIVATING;
748         }
749
750         dbg("cid = %d", tcore_context_get_id(ps_context));
751
752         tcore_context_set_state(ps_context, CONTEXT_STATE_ACTIVATING);
753         rv = po->ops->activate_context(o, ps_context, user_data);
754         if(rv != TCORE_RETURN_SUCCESS)
755                 tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
756
757         return rv;
758 }
759
760 TReturn tcore_ps_deactivate_context(CoreObject *o, CoreObject *ps_context, void *user_data)
761 {
762         int rv;
763         struct private_object_data *po = NULL;
764         enum co_context_state context_state = CONTEXT_STATE_DEACTIVATED;
765
766         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
767
768         po = tcore_object_ref_object(o);
769         if (!po)
770                 return TCORE_RETURN_EINVAL;
771
772         if (!po->online) {
773                 dbg("ps network is not online !");
774                 return TCORE_RETURN_PS_NETWORK_NOT_READY;
775         }
776
777         if (!ps_context)
778                 return TCORE_RETURN_EINVAL;
779
780         rv = _ps_is_active_context(o, ps_context);
781         if (!rv)
782                 return TCORE_RETURN_EINVAL;
783
784         rv = _ps_is_duplicated_apn(o, ps_context);
785         if (rv) {
786                 unsigned char cid = 0;
787                 cid = tcore_context_get_id(ps_context);
788                 po->cid[cid].contexts = g_slist_remove(po->cid[cid].contexts, ps_context);
789                 tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATED);
790                 return TCORE_RETURN_SUCCESS;
791         }
792
793         context_state = tcore_context_get_state(ps_context);
794         if (context_state == CONTEXT_STATE_DEACTIVATED){
795                 dbg("Context State : CONTEXT_STATE_DEACTIVATED");
796                 return TCORE_RETURN_SUCCESS;
797         }
798         else if (context_state == CONTEXT_STATE_DEACTIVATING){
799                 dbg("Context State : CONTEXT_STATE_DEACTIVATING");
800                 return TCORE_RETURN_SUCCESS;
801         }
802         else if (context_state == CONTEXT_STATE_ACTIVATING){
803                 dbg("Context State :CONTEXT_STATE_ACTIVATING");
804                 return TCORE_RETURN_PS_ACTIVATING;
805         }
806         tcore_context_set_state(ps_context, CONTEXT_STATE_DEACTIVATING);
807
808         rv = po->ops->deactivate_context(o, ps_context, user_data);
809         if(rv != TCORE_RETURN_SUCCESS)
810                 tcore_context_set_state(ps_context, CONTEXT_STATE_ACTIVATED);
811
812         return rv;
813 }
814
815 TReturn tcore_ps_deactivate_contexts(CoreObject *o)
816 {
817         int temp_index = 0;
818         struct private_object_data *po = NULL;
819         GSList *contexts = NULL;
820
821         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
822
823         po = tcore_object_ref_object(o);
824         if (!po)
825                 return TCORE_RETURN_EINVAL;
826
827         if (!po->online) {
828                 dbg("ps network is not online !");
829                 return TCORE_RETURN_PS_NETWORK_NOT_READY;
830         }
831
832         for (temp_index = 1; temp_index <= po->num_of_pdn; temp_index++) {
833                 if (po->cid[temp_index].cid != 0) {
834                         contexts = po->cid[temp_index].contexts;
835                         if(!contexts)
836                                 continue;
837
838                         g_slist_foreach (contexts, _deactivate_context, o);
839                 }
840         }
841
842         return TCORE_RETURN_SUCCESS;
843 }
844
845 TReturn tcore_ps_deactivate_cid(CoreObject *o, unsigned int cid)
846 {
847         int temp_index = 0;
848         struct private_object_data *po = NULL;
849         GSList *contexts = NULL;
850
851         CORE_OBJECT_CHECK_RETURN(o, CORE_OBJECT_TYPE_PS, TCORE_RETURN_EINVAL);
852
853         po = tcore_object_ref_object(o);
854         if (!po)
855                 return TCORE_RETURN_EINVAL;
856
857         if (!po->online) {
858                 dbg("ps network is not online !");
859                 return TCORE_RETURN_PS_NETWORK_NOT_READY;
860         }
861
862         for (temp_index = 1; temp_index <= po->num_of_pdn; temp_index++) {
863                 if (po->cid[temp_index].cid != 0 && po->cid[temp_index].cid == cid) {
864                         contexts = po->cid[temp_index].contexts;
865                         if(!contexts)
866                                 continue;
867
868                         g_slist_foreach (contexts, _deactivate_context, o);
869                 }
870         }
871
872         return TCORE_RETURN_SUCCESS;
873 }