52f6bc15d4d5a8f5e20f109f06ecb15a6b29594e
[framework/telephony/libtcore.git] / src / core_object.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 "core_object.h"
30 #include "hal.h"
31 #include "at.h"
32
33 struct callback_type {
34         CoreObject *co;
35         char *event;
36         CoreObjectCallback callback;
37         void *user_data;
38 };
39
40 struct tcore_object_type {
41         unsigned int type;
42         char *name;
43
44         TcorePlugin *parent_plugin;
45
46         void *object;
47         void *user_data;
48
49         CoreObjectFreeHook free_hook;
50         CoreObjectCloneHook clone_hook;
51         CoreObjectDispatcher dispatcher;
52         GSList *callbacks;
53
54         TcoreHal *hal;
55 };
56
57 static CoreObject *_object_new(TcorePlugin *plugin, const char *name, unsigned int type)
58 {
59         CoreObject *co;
60
61         co = calloc(sizeof(struct tcore_object_type), 1);
62         if (!co)
63                 return NULL;
64
65         co->parent_plugin = plugin;
66
67         if (name)
68                 co->name = strdup(name);
69
70         co->type = type;
71
72         return co;
73 }
74
75 static gboolean _on_at_event(TcoreAT *at, const GSList *lines, void *user_data)
76 {
77         gboolean ret;
78
79         struct callback_type *cb = user_data;
80
81         ret = cb->callback(cb->co, lines, cb->user_data);
82         if (ret == FALSE) {
83
84         }
85
86         return ret;
87 }
88
89 static void _remove_at_callback(TcoreAT *at, struct callback_type *cb)
90 {
91         tcore_at_remove_notification_full(at, cb->event, _on_at_event, cb);
92 }
93
94 CoreObject *tcore_object_new(TcorePlugin *plugin,
95                 const char *name, TcoreHal *hal)
96 {
97         CoreObject *co;
98
99         co = _object_new(plugin, name, CORE_OBJECT_TYPE_DEFAULT);
100         if (!co)
101                 return NULL;
102
103         tcore_object_set_hal(co, hal);
104
105         if (plugin)
106                 tcore_plugin_add_core_object(plugin, co);
107
108         return co;
109 }
110
111 void tcore_object_free(CoreObject *co)
112 {
113         GSList *l = NULL;
114         struct callback_type *cb = NULL;
115
116         if (!co)
117                 return;
118
119         dbg("co_name=%s", co->name);
120
121         if (co->free_hook)
122                 co->free_hook(co);
123
124         if (co->callbacks) {
125                 for (l = co->callbacks; l; l = l->next) {
126                         if (!l)
127                                 continue;
128
129                         cb = l->data;
130                         if (!cb)
131                                 continue;
132
133                         if (cb->event)
134                                 g_free(cb->event);
135
136                         g_free(cb);
137                 }
138
139                 g_slist_free(co->callbacks);
140                 co->callbacks = NULL;
141         }
142
143         if (co->name)
144                 g_free(co->name);
145
146         g_free(co);
147 }
148
149 CoreObject *tcore_object_clone(CoreObject *src, TcorePlugin *new_parent, const char *new_name)
150 {
151         CoreObject *dest;
152         TcorePlugin *p;
153         const char *name;
154         GSList *l = NULL;
155         struct callback_type *cb = NULL;
156
157         if (!src)
158                 return NULL;
159
160         if (new_parent)
161                 p = new_parent;
162         else
163                 p = src->parent_plugin;
164
165         if (new_name)
166                 name = new_name;
167         else
168                 name = src->name;
169
170         dest = _object_new(p, name, src->type);
171         if (!dest)
172                 return NULL;
173
174         dest->object = src->object;
175         dest->user_data = src->user_data;
176         dest->free_hook = src->free_hook;
177         dest->clone_hook = src->clone_hook;
178         dest->dispatcher = src->dispatcher;
179         dest->hal = src->hal;
180
181         for (l = src->callbacks; l; l = l->next) {
182                 if (!l)
183                         continue;
184
185                 cb = l->data;
186                 if (!cb)
187                         continue;
188
189                 tcore_object_add_callback(dest, cb->event, cb->callback, cb->user_data);
190         }
191
192         tcore_plugin_add_core_object(p, dest);
193
194         if (src->clone_hook)
195                 src->clone_hook(src, dest);
196
197         return dest;
198 }
199
200 const char *tcore_object_ref_name(CoreObject *co)
201 {
202         if (!co)
203                 return NULL;
204
205         return co->name;
206 }
207
208 TReturn tcore_object_set_free_hook(CoreObject *co,
209                 CoreObjectFreeHook free_hook)
210 {
211         if (!co)
212                 return TCORE_RETURN_EINVAL;
213
214         co->free_hook = free_hook;
215
216         return TCORE_RETURN_SUCCESS;
217 }
218
219
220 TReturn tcore_object_set_clone_hook(CoreObject *co,
221                 CoreObjectCloneHook clone_hook)
222 {
223         if (!co)
224                 return TCORE_RETURN_EINVAL;
225
226         co->clone_hook = clone_hook;
227
228         return TCORE_RETURN_SUCCESS;
229 }
230
231 TReturn tcore_object_set_name(CoreObject *co, const char *name)
232 {
233         if (!co)
234                 return TCORE_RETURN_EINVAL;
235
236         if (co->name) {
237                 free(co->name);
238                 co->name = NULL;
239         }
240
241         if (name)
242                 co->name = strdup(name);
243
244         return TCORE_RETURN_SUCCESS;
245 }
246
247 TcorePlugin *tcore_object_ref_plugin(CoreObject *co)
248 {
249         if (!co)
250                 return NULL;
251
252         return co->parent_plugin;
253 }
254
255 TReturn tcore_object_link_object(CoreObject *co, void *object)
256 {
257         if (!co)
258                 return TCORE_RETURN_EINVAL;
259
260         co->object = object;
261
262         return TCORE_RETURN_SUCCESS;
263 }
264
265 void *tcore_object_ref_object(CoreObject *co)
266 {
267         if (!co)
268                 return NULL;
269
270         return co->object;
271 }
272
273 TReturn tcore_object_set_type(CoreObject *co, unsigned int type)
274 {
275         if (!co)
276                 return TCORE_RETURN_EINVAL;
277
278         co->type = type;
279
280         return TCORE_RETURN_SUCCESS;
281 }
282
283 unsigned int tcore_object_get_type(CoreObject *co)
284 {
285         if (!co)
286                 return 0;
287
288         return co->type;
289 }
290
291 TReturn tcore_object_set_hal(CoreObject *co, TcoreHal *hal)
292 {
293         TcoreAT *at;
294         struct callback_type *cb = NULL;
295         GSList *l = NULL;
296
297         if (!co)
298                 return TCORE_RETURN_EINVAL;
299
300         if (co->hal) {
301                 // remove unsolicited callbacks
302                 if (tcore_hal_get_mode(co->hal) == TCORE_HAL_MODE_AT) {
303                         at = tcore_hal_get_at(co->hal);
304                         for (l = co->callbacks; l; l = l->next) {
305                                 if (!l)
306                                         continue;
307
308                                 cb = l->data;
309                                 if (!cb)
310                                         continue;
311
312                                 tcore_at_remove_notification_full(at, cb->event, _on_at_event, cb);
313                         }
314                 }
315         }
316
317         co->hal = hal;
318         if (!hal)
319                 return TCORE_RETURN_SUCCESS;
320
321         // register unsolicited callbacks
322         if (tcore_hal_get_mode(hal) == TCORE_HAL_MODE_AT) {
323                 at = tcore_hal_get_at(hal);
324                 for (l = co->callbacks; l; l = l->next) {
325                         if (!l)
326                                 continue;
327
328                         cb = l->data;
329                         if (!cb)
330                                 continue;
331
332                         if (cb->event[0] == 27)
333                                 tcore_at_add_notification(at, cb->event + 1, TRUE, _on_at_event, cb);
334                         else
335                                 tcore_at_add_notification(at, cb->event, FALSE, _on_at_event, cb);
336                 }
337         }
338
339         return TCORE_RETURN_SUCCESS;
340 }
341
342 TcoreHal *tcore_object_get_hal(CoreObject *co)
343 {
344         if (!co)
345                 return NULL;
346
347         return co->hal;
348 }
349
350 TReturn tcore_object_link_user_data(CoreObject *co,
351                 void *user_data)
352 {
353         if (!co)
354                 return TCORE_RETURN_EINVAL;
355
356         co->user_data = user_data;
357
358         return TCORE_RETURN_SUCCESS;
359 }
360
361 void *tcore_object_ref_user_data(CoreObject *co)
362 {
363         if (!co)
364                 return NULL;
365
366         return co->user_data;
367 }
368
369 TReturn tcore_object_dispatch_request(CoreObject *co,
370                 UserRequest *ur)
371 {
372         if (!co || !ur)
373                 return TCORE_RETURN_EINVAL;
374
375         if (!co->dispatcher)
376                 return TCORE_RETURN_ENOSYS;
377
378         return co->dispatcher(co, ur);
379 }
380
381 TReturn tcore_object_set_dispatcher(CoreObject *co,
382                 CoreObjectDispatcher func)
383 {
384         if (!co || !func)
385                 return TCORE_RETURN_EINVAL;
386
387         co->dispatcher = func;
388
389         return TCORE_RETURN_SUCCESS;
390 }
391
392 TReturn tcore_object_add_callback(CoreObject *co,
393                 const char *event,
394                 CoreObjectCallback callback, void *user_data)
395 {
396         struct callback_type *cb = NULL;
397         TcoreAT *at = NULL;
398
399         if (!co || !event || !callback)
400                 return TCORE_RETURN_EINVAL;
401
402         if (strlen(event) < 1)
403                 return TCORE_RETURN_EINVAL;
404
405         cb = calloc(sizeof(struct callback_type), 1);
406         if (!cb)
407                 return TCORE_RETURN_ENOMEM;
408
409         cb->co = co;
410         cb->event = strdup(event);
411         cb->callback = callback;
412         cb->user_data = user_data;
413
414         co->callbacks = g_slist_append(co->callbacks, cb);
415
416         if (co->hal) {
417                 if (tcore_hal_get_mode(co->hal) == TCORE_HAL_MODE_AT) {
418                         at = tcore_hal_get_at(co->hal);
419                         if (event[0] == 27)
420                                 tcore_at_add_notification(at, cb->event + 1, TRUE, _on_at_event, cb);
421                         else
422                                 tcore_at_add_notification(at, cb->event, FALSE, _on_at_event, cb);
423
424                 }
425         }
426
427         return TCORE_RETURN_SUCCESS;
428 }
429
430 TReturn tcore_object_del_callback(CoreObject *co,
431                 const char *event, CoreObjectCallback callback)
432 {
433         struct callback_type *cb = NULL;
434         GSList *l = NULL;
435         TcoreAT *at = NULL;
436
437         if (!co || !event || !callback || !co->callbacks)
438                 return TCORE_RETURN_EINVAL;
439
440         if (strlen(event) < 1)
441                 return TCORE_RETURN_EINVAL;
442
443         if (co->hal) {
444                 if (tcore_hal_get_mode(co->hal) == TCORE_HAL_MODE_AT)
445                         at = tcore_hal_get_at(co->hal);
446         }
447
448         for (l = co->callbacks; l; l = l->next) {
449                 if (!l)
450                         continue;
451
452                 cb = l->data;
453                 if (!cb)
454                         continue;
455
456                 if (cb->callback != callback)
457                         continue;
458
459                 if (g_strcmp0(cb->event, event) != 0)
460                         continue;
461
462                 if (at)
463                         _remove_at_callback(at, cb);
464
465                 free(cb->event);
466                 co->callbacks = g_slist_remove(co->callbacks, cb);
467                 free(cb);
468         }
469
470         return TCORE_RETURN_SUCCESS;
471 }
472
473 TReturn tcore_object_emit_callback(CoreObject *co,
474                 const char *event, const void *event_info)
475 {
476         struct callback_type *cb = NULL;
477         GSList *l = NULL;
478         TReturn ret;
479
480         if (!co || !event)
481                 return TCORE_RETURN_EINVAL;
482
483         l = co->callbacks;
484         while (l) {
485                 cb = l->data;
486                 if (!cb) {
487                         l = l->next;
488                         continue;
489                 }
490
491                 if (g_strcmp0(cb->event, event) != 0) {
492                         l = l->next;
493                         continue;
494                 }
495
496                 if (cb->callback) {
497                         ret = cb->callback(co, event_info, cb->user_data);
498                         if (ret == FALSE) {
499                                 l = l->next;
500                                 co->callbacks = g_slist_remove(co->callbacks, cb);
501                                 continue;
502                         }
503                 }
504
505                 l = l->next;
506         }
507
508         return TCORE_RETURN_SUCCESS;
509 }