hal: Implement network interface setup
[platform/core/telephony/libtcore.git] / src / hal.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 <string.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <time.h>
27
28 #include <glib.h>
29
30 #include "tcore.h"
31 #include "hal.h"
32 #include "at.h"
33 #include "queue.h"
34 #include "plugin.h"
35 #include "user_request.h"
36 #include "server.h"
37 #include "mux.h"
38
39
40 //#define IDLE_SEND_PRIORITY G_PRIORITY_DEFAULT
41 #define IDLE_SEND_PRIORITY G_PRIORITY_HIGH
42
43 struct hook_send_type {
44         TcoreHalSendHook func;
45         void *user_data;
46 };
47
48 struct recv_callback_item_type {
49         TcoreHalReceiveCallback func;
50         void *user_data;
51 };
52
53 struct tcore_hal_type {
54         TcorePlugin *parent_plugin;
55         TcoreQueue *queue;
56         char *name;
57         struct tcore_hal_operations *ops;
58         void *user_data;
59         GSList *callbacks;
60         gboolean power_state;
61         GSList *hook_list_send;
62
63         enum tcore_hal_mode mode;
64         TcoreAT *at;
65 };
66
67 static gboolean _hal_idle_send(void *user_data)
68 {
69         TcoreHal *h = user_data;
70         TcorePending *p = NULL;
71         TcoreQueue *q;
72         int ret = 0;
73         void *data = NULL;
74         unsigned int data_len = 0;
75         gboolean renew = FALSE;
76
77         if (!h)
78                 return FALSE;
79
80         msg("--[Queue SEND]-------------------");
81
82         p = tcore_queue_ref_next_pending(h->queue);
83         if (!p) {
84                 dbg("next pending is NULL. no send, queue len=%d", tcore_queue_get_length(h->queue));
85                 goto out;
86         }
87
88         data = tcore_pending_ref_request_data(p, &data_len);
89         dbg("queue len=%d, pending=0x%x, id=0x%x, data_len=%d",
90                         tcore_queue_get_length(h->queue), (unsigned int)p, tcore_pending_get_id(p), data_len);
91
92         if (h->mode == TCORE_HAL_MODE_AT) {
93                 ret = tcore_at_set_request(h->at, data, TRUE);
94         }
95         else {
96                 ret = tcore_hal_send_data(h, data_len, data);
97         }
98
99         if (ret == TCORE_RETURN_SUCCESS) {
100                 tcore_pending_emit_send_callback(p, TRUE);
101         }
102         else {
103                 tcore_pending_emit_send_callback(p, FALSE);
104         }
105
106         if (ret != TCORE_RETURN_HOOK_STOP) {
107                 if (tcore_pending_get_auto_free_status_after_sent(p)) {
108                         q = tcore_hal_ref_queue(h);
109                         tcore_queue_pop_by_pending(q, p);
110                         tcore_pending_free(p);
111
112                         /* renew idler */
113                         renew = TRUE;
114                 }
115                 else {
116                         /* Send fail */
117                         if (ret != TCORE_RETURN_SUCCESS) {
118                                 dbg("send fail.");
119                                 q = tcore_hal_ref_queue(h);
120                                 p = tcore_queue_pop(q);
121                                 tcore_pending_free(p);
122                         }
123                 }
124         }
125
126 out:
127         msg("--[Queue SEND FINISH]------------\n");
128         return renew;
129 }
130
131 TcoreHal *tcore_hal_new(TcorePlugin *plugin, const char *name,
132                 struct tcore_hal_operations *hops,
133                 enum tcore_hal_mode mode)
134 {
135         TcoreHal *h;
136
137         if (!name)
138                 return NULL;
139
140         h = calloc(1, sizeof(struct tcore_hal_type));
141         if (!h)
142                 return NULL;
143
144         h->parent_plugin = plugin;
145         h->ops = hops;
146         h->name = strdup(name);
147         h->queue = tcore_queue_new(h);
148         h->mode = mode;
149
150         if (mode == TCORE_HAL_MODE_AT)
151                 h->at = tcore_at_new(h);
152
153         if (plugin)
154                 tcore_server_add_hal(tcore_plugin_ref_server(plugin), h);
155
156         return h;
157 }
158
159 void tcore_hal_free(TcoreHal *hal)
160 {
161         if (!hal)
162                 return;
163
164         dbg("hal=%s", hal->name);
165
166         if (hal->name)
167                 free(hal->name);
168
169         if (hal->callbacks)
170                 g_slist_free(hal->callbacks);
171
172         if (hal->queue)
173                 tcore_queue_free(hal->queue);
174
175         if (hal->at)
176                 tcore_at_free(hal->at);
177
178         free(hal);
179 }
180
181 TReturn tcore_hal_set_name(TcoreHal *hal, const char *name)
182 {
183         if (!hal)
184                 return TCORE_RETURN_EINVAL;
185
186         if (hal->name) {
187                 free(hal->name);
188                 hal->name = NULL;
189         }
190
191         if (name)
192                 hal->name = strdup(name);
193
194         return TCORE_RETURN_SUCCESS;
195 }
196
197 char *tcore_hal_get_name(TcoreHal *hal)
198 {
199         if (!hal)
200                 return NULL;
201
202         if (hal->name)
203                 return strdup(hal->name);
204
205         return NULL;
206 }
207
208 TcoreAT *tcore_hal_get_at(TcoreHal *hal)
209 {
210         if (!hal)
211                 return NULL;
212
213         return hal->at;
214 }
215
216 enum tcore_hal_mode tcore_hal_get_mode(TcoreHal *hal)
217 {
218         if (!hal)
219                 return TCORE_HAL_MODE_UNKNOWN;
220
221         return hal->mode;
222 }
223
224 TReturn tcore_hal_set_mode(TcoreHal *hal, enum tcore_hal_mode mode)
225 {
226         if (!hal)
227                 return TCORE_RETURN_EINVAL;
228
229         hal->mode = mode;
230
231         return TCORE_RETURN_SUCCESS;
232 }
233
234 TReturn tcore_hal_link_user_data(TcoreHal *hal, void *user_data)
235 {
236         if (!hal)
237                 return TCORE_RETURN_EINVAL;
238
239         hal->user_data = user_data;
240
241         return TCORE_RETURN_SUCCESS;
242 }
243
244 void *tcore_hal_ref_user_data(TcoreHal *hal)
245 {
246         if (!hal)
247                 return NULL;
248
249         return hal->user_data;
250 }
251
252 /* Send data without Queue */
253 TReturn tcore_hal_send_data(TcoreHal *hal, unsigned int data_len, void *data)
254 {
255         struct hook_send_type *hook;
256         GSList *list;
257
258         if (!hal || !hal->ops || !hal->ops->send)
259                 return TCORE_RETURN_EINVAL;
260
261         for (list = hal->hook_list_send; list; list = list->next) {
262                 hook = list->data;
263                 if (!hook) {
264                         continue;
265                 }
266
267                 if (hook->func(hal, data_len, data, hook->user_data) == TCORE_HOOK_RETURN_STOP_PROPAGATION) {
268                         return TCORE_RETURN_HOOK_STOP;
269                 }
270         }
271
272         return hal->ops->send(hal, data_len, data);
273 }
274
275 /* Send data by Queue */
276 TReturn tcore_hal_send_request(TcoreHal *hal, TcorePending *pending)
277 {
278         int qlen = 0;
279         enum tcore_pending_priority priority;
280
281         if (!hal || !pending)
282                 return TCORE_RETURN_EINVAL;
283
284         if (hal->power_state == FALSE)
285                 return TCORE_RETURN_FAILURE;
286
287         qlen = tcore_queue_get_length(hal->queue);
288         tcore_queue_push(hal->queue, pending);
289
290         tcore_pending_get_priority(pending, &priority);
291         if (priority == TCORE_PENDING_PRIORITY_IMMEDIATELY) {
292                 dbg("IMMEDIATELY pending !!");
293                 _hal_idle_send(hal);
294         }
295         else {
296                 if (tcore_queue_get_length(hal->queue) == 1) {
297                         g_idle_add_full(IDLE_SEND_PRIORITY, _hal_idle_send, hal, NULL);
298                 }
299         }
300
301         return TCORE_RETURN_SUCCESS;
302 }
303
304 TReturn tcore_hal_send_force(TcoreHal *hal)
305 {
306         if (!hal)
307                 return TCORE_RETURN_EINVAL;
308
309         _hal_idle_send(hal);
310
311         return TCORE_RETURN_SUCCESS;
312 }
313
314 TReturn tcore_hal_dispatch_response_data(TcoreHal *hal, int id,
315                 unsigned int data_len, const void *data)
316 {
317         TcorePending *p = NULL;
318
319         if (!hal)
320                 return TCORE_RETURN_EINVAL;
321
322         if (data_len > 0 && data == NULL)
323                 return TCORE_RETURN_EINVAL;
324
325         if (hal->mode == TCORE_HAL_MODE_AT) {
326                 gboolean ret;
327                 ret = tcore_at_process(hal->at, data_len, data);
328                 if (ret) {
329                         /* Send next request in queue */
330                         g_idle_add_full(IDLE_SEND_PRIORITY, _hal_idle_send, hal, NULL );
331                 }
332         }
333         else {
334                 if(hal->mode == TCORE_HAL_MODE_CUSTOM) {
335                         dbg("TCORE_HAL_MODE_CUSTOM");
336                         p = tcore_queue_pop_by_id(hal->queue, id);
337                         if (!p) {
338                                 dbg("unknown pending (id=0x%x)", id);
339                                 return TCORE_RETURN_PENDING_WRONG_ID;
340                         }
341
342                         tcore_pending_emit_response_callback(p, data_len, data);
343                         tcore_user_request_free(tcore_pending_ref_user_request(p));
344                         tcore_pending_free(p);
345                 }
346                 else if(hal->mode == TCORE_HAL_MODE_TRANSPARENT) {
347                         dbg("TCORE_HAL_MODE_TRANSPARENT");
348
349                         /* Invoke CMUX receive API for decoding */
350                         tcore_cmux_rcv_from_hal((unsigned char *)data, data_len);
351                 }
352                 /* Send next request in queue */
353                 g_idle_add_full(IDLE_SEND_PRIORITY, _hal_idle_send, hal, NULL );
354         }
355
356         return TCORE_RETURN_SUCCESS;
357 }
358
359 TReturn tcore_hal_add_recv_callback(TcoreHal *hal, TcoreHalReceiveCallback func,
360                 void *user_data)
361 {
362         struct recv_callback_item_type *item;
363
364         if (!hal)
365                 return TCORE_RETURN_EINVAL;
366
367         item = calloc(1, sizeof(struct recv_callback_item_type));
368         if (!item)
369                 return TCORE_RETURN_ENOMEM;
370
371         item->func = func;
372         item->user_data = user_data;
373
374         hal->callbacks = g_slist_append(hal->callbacks, item);
375
376         return TCORE_RETURN_SUCCESS;
377 }
378
379 TReturn tcore_hal_remove_recv_callback(TcoreHal *hal, TcoreHalReceiveCallback func)
380 {
381         struct recv_callback_item_type *item;
382         GSList *list;
383
384         if (!hal)
385                 return TCORE_RETURN_EINVAL;
386
387         for (list = hal->callbacks; list; list = list->next) {
388                 item = list->data;
389                 if (!item) {
390                         continue;
391                 }
392
393                 if (item->func == func) {
394                         hal->callbacks = g_slist_remove(hal->callbacks, item);
395                         free(item);
396                         if (!hal->callbacks)
397                                 break;
398
399                         list = hal->callbacks;
400                 }
401         }
402
403         return TCORE_RETURN_SUCCESS;
404 }
405
406 TReturn tcore_hal_emit_recv_callback(TcoreHal *hal, unsigned int data_len,
407                 const void *data)
408 {
409         GSList *list;
410         struct recv_callback_item_type *item;
411
412         if (!hal)
413                 return TCORE_RETURN_EINVAL;
414
415         for (list = hal->callbacks; list; list = list->next) {
416                 item = list->data;
417
418                 if (item) {
419                         item->func(hal, data_len, data, item->user_data);
420                 }
421         }
422
423         return TCORE_RETURN_SUCCESS;
424 }
425
426
427 TReturn tcore_hal_add_send_hook(TcoreHal *hal, TcoreHalSendHook func, void *user_data)
428 {
429         struct hook_send_type *hook;
430
431         if (!hal || !func)
432                 return TCORE_RETURN_EINVAL;
433
434         hook = calloc(1, sizeof(struct hook_send_type));
435         if (!hook)
436                 return TCORE_RETURN_ENOMEM;
437
438         hook->func = func;
439         hook->user_data = user_data;
440
441         hal->hook_list_send = g_slist_append(hal->hook_list_send, hook);
442
443         return TCORE_RETURN_SUCCESS;
444 }
445
446 TReturn tcore_hal_remove_send_hook(TcoreHal *hal, TcoreHalSendHook func)
447 {
448         struct hook_send_type *hook;
449         GSList *list;
450
451         if (!hal)
452                 return TCORE_RETURN_EINVAL;
453
454         for (list = hal->hook_list_send; list; list = list->next) {
455                 hook = list->data;
456                 if (!hook) {
457                         continue;
458                 }
459
460                 if (hook->func == func) {
461                         hal->hook_list_send = g_slist_remove(hal->hook_list_send, hook);
462                         free(hook);
463                         list = hal->hook_list_send;
464                 }
465         }
466
467         return TCORE_RETURN_SUCCESS;
468 }
469
470 TcoreQueue *tcore_hal_ref_queue(TcoreHal *hal)
471 {
472         if (!hal)
473                 return NULL;
474
475         return hal->queue;
476 }
477
478 TcorePlugin *tcore_hal_ref_plugin(TcoreHal *hal)
479 {
480         if (!hal)
481                 return NULL;
482
483         return hal->parent_plugin;
484 }
485
486 TReturn tcore_hal_set_power_state(TcoreHal *hal, gboolean flag)
487 {
488         if (!hal)
489                 return TCORE_RETURN_EINVAL;
490
491         hal->power_state = flag;
492
493         return TCORE_RETURN_SUCCESS;
494 }
495
496 gboolean tcore_hal_get_power_state(TcoreHal *hal)
497 {
498         if (!hal)
499                 return FALSE;
500
501         return hal->power_state;
502 }
503
504 TReturn tcore_hal_set_power(TcoreHal *hal, gboolean flag)
505 {
506         if (!hal || !hal->ops || !hal->ops->power)
507                 return TCORE_RETURN_EINVAL;
508
509         return hal->ops->power(hal, flag);
510 }
511
512 TReturn tcore_hal_setup_netif(TcoreHal *hal, CoreObject *co,
513                                 TcoreHalSetupNetifCallback func,
514                                 void *user_data, unsigned int cid,
515                                 gboolean enable)
516 {
517         if (!hal || !hal->ops || !hal->ops->setup_netif)
518                 return TCORE_RETURN_EINVAL;
519
520         return hal->ops->setup_netif(co, func, user_data, cid, enable);
521 }