Upgradation to New Design.
[platform/core/telephony/tel-plugin-vmodem.git] / src / desc-vmodem.c
1 /*
2  * tel-plugin-vmodem
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Junhwan An <jh48.an@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 #include <fcntl.h>
28
29 #include <glib.h>
30
31 #include <tcore.h>
32 #include <plugin.h>
33 #include <server.h>
34 #include <user_request.h>
35 #include <hal.h>
36 #include <core_object.h>
37
38 #include "vdpram.h"
39
40 #define SERVER_INIT_WAIT_TIMEOUT                500
41
42 #define DEVICE_NAME_LEN_MAX                             16
43 #define DEVICE_NAME_PREFIX                              "pdp"
44
45 #define BUF_LEN_MAX                                             512
46
47 #define CORE_OBJECT_NAME_MAX                    16
48
49 #define MODEM_PLUGIN_NAME                               "atmodem-plugin.so"
50
51 struct custom_data {
52         int vdpram_fd;
53         guint watch_id_vdpram;
54 };
55
56 struct v_modules {
57         unsigned int co_type;
58         char co_name[CORE_OBJECT_NAME_MAX];
59 };
60
61 /* Supported Modules */
62 static struct v_modules supported_modules[] = {
63         {CORE_OBJECT_TYPE_MODEM,        "Modem"},
64         {CORE_OBJECT_TYPE_CALL,         "Call"},
65         {CORE_OBJECT_TYPE_SS,           "SS"},
66         {CORE_OBJECT_TYPE_NETWORK,      "Network"},
67         {CORE_OBJECT_TYPE_PS,           "PS"},
68         {CORE_OBJECT_TYPE_SIM,          "SIM"},
69         {CORE_OBJECT_TYPE_SMS,          "SMS"},
70         {0,                                                     ""}
71 };
72
73 static void _assign_objects_to_hal(TcoreHal *hal)
74 {
75         TcorePlugin *plugin;
76         int i;
77         gboolean ret;
78
79         plugin = tcore_hal_ref_plugin(hal);
80
81         /* Add Core Object type for specific 'hal' */
82         for (i = 0 ; supported_modules[i].co_type != 0 ; i++) {
83                 ret = tcore_server_add_cp_mapping_tbl_entry(plugin,
84                                                                         supported_modules[i].co_type, hal);
85                 if (ret == TRUE) {
86                         dbg("[VMODEM] Core Object: [%s] - [Success]",
87                                                                         supported_modules[i].co_name);
88                 } else {
89                         err("[VMODEM] Core Object: [%s] - [Fail]",
90                                                                         supported_modules[i].co_name);
91                 }
92         }
93 }
94
95 static void _deassign_objects_from_hal(TcoreHal *hal)
96 {
97         TcorePlugin *plugin;
98
99         plugin = tcore_hal_ref_plugin(hal);
100
101         /* Remove mapping table entry */
102         tcore_server_remove_cp_mapping_tbl_entry(plugin, hal);
103 }
104
105 static guint _register_gio_watch(TcoreHal *h, int fd, void *callback)
106 {
107         GIOChannel *channel = NULL;
108         guint source;
109
110         dbg("[VMODEM] Register to Watch list - fd: [%d]", fd);
111
112         if ((fd < 0) || (callback == NULL))
113                 return 0;
114
115         channel = g_io_channel_unix_new(fd);
116         source = g_io_add_watch(channel, G_IO_IN, (GIOFunc) callback, h);
117         g_io_channel_unref(channel);
118         channel = NULL;
119
120         return source;
121 }
122
123 static void _deregister_gio_watch(guint watch_id)
124 {
125         dbg("[VMODEM] Deregister Watch ID: [%d]", watch_id);
126
127         /* Remove source */
128         g_source_remove(watch_id);
129 }
130
131 static gboolean _load_modem_plugin(gpointer data)
132 {
133         TcoreHal *hal;
134         TcorePlugin *plugin;
135         struct custom_data *user_data;
136
137         dbg("[VMMODEM] Entry");
138
139         if (data == NULL) {
140                 err("[VMMODEM] data is NULL");
141                 return FALSE;
142         }
143
144         hal = data;
145         plugin = tcore_hal_ref_plugin(hal);
146
147         /* Load Modem Plug-in */
148         if (tcore_server_load_modem_plugin(tcore_plugin_ref_server(plugin),
149                                         plugin, MODEM_PLUGIN_NAME) == TCORE_RETURN_FAILURE) {
150                 err("[VMMODEM] Load Modem Plug-in - [FAIL]");
151
152                 /* Clean-up */
153                 _deassign_objects_from_hal(hal);
154
155                 goto EXIT;
156         } else {
157                 dbg("[VMMODEM] Load Modem Plug-in - [SUCCESS]");
158         }
159
160         /* To stop the cycle need to return FALSE */
161         return FALSE;
162
163 EXIT:
164         user_data = tcore_hal_ref_user_data(hal);
165         if (user_data == NULL)
166                 return FALSE;
167
168         /* Deregister from Watch list */
169         _deregister_gio_watch(user_data->watch_id_vdpram);
170
171         /* Free HAL */
172         tcore_hal_free(hal);
173
174         /* Close VDPRAM device */
175         vdpram_close(user_data->vdpram_fd);
176
177         /* Free custom data */
178         g_free(user_data);
179
180         return FALSE;
181 }
182
183 static TReturn _modem_power(TcoreHal *hal, gboolean enable)
184 {
185         struct custom_data *user_data;
186
187         user_data = tcore_hal_ref_user_data(hal);
188         if (user_data == NULL) {
189                 err("[VMODEM] User data is NULL");
190                 return TCORE_RETURN_FAILURE;
191         }
192
193         if (enable == TRUE) {                                                   /* POWER ON */
194                 if (FALSE == vdpram_poweron(user_data->vdpram_fd)) {
195                         err("[VMODEM] Power ON - [FAIL]");
196                         return TCORE_RETURN_FAILURE;
197                 }
198
199                 /* Set Power State - ON */
200                 tcore_hal_set_power_state(hal, TRUE);
201         } else {                                                                                /* POWER OFF */
202                 if (vdpram_poweroff(user_data->vdpram_fd) == FALSE) {
203                         err("[VMODEM] Power OFF - [FAIL]");
204                         return TCORE_RETURN_FAILURE;
205                 }
206
207                 /* Set Power state - OFF */
208                 tcore_hal_set_power_state(hal, FALSE);
209         }
210
211         return TCORE_RETURN_SUCCESS;
212 }
213
214 static gboolean on_recv_vdpram_message(GIOChannel *channel,
215                                                                         GIOCondition condition, gpointer data)
216 {
217         TcoreHal *hal = data;
218         struct custom_data *custom;
219         char buf[BUF_LEN_MAX];
220         int n = 0;
221
222         custom = tcore_hal_ref_user_data(hal);
223         memset(buf, 0x0, BUF_LEN_MAX);
224
225         /* Read from Device */
226         n = vdpram_tty_read(custom->vdpram_fd, buf, BUF_LEN_MAX);
227         if (n < 0) {
228                 err("[VMODEM] Read error - Data received: [%d]", n);
229                 return TRUE;
230         }
231         dbg("[VMODEM] DPRAM Receive - Data length: [%d]", n);
232
233         /* Emit receive callback */
234         tcore_hal_emit_recv_callback(hal, n, buf);
235
236         return TRUE;
237 }
238
239 static TReturn hal_power(TcoreHal *hal, gboolean flag)
240 {
241         return _modem_power(hal, flag);
242 }
243
244 static TReturn hal_send(TcoreHal *hal, unsigned int data_len, void *data)
245 {
246         int ret;
247         struct custom_data *user_data;
248
249         if (tcore_hal_get_power_state(hal) == FALSE) {
250                 err("[VMODEM] HAL Power state - OFF");
251                 return TCORE_RETURN_FAILURE;
252         }
253
254         user_data = tcore_hal_ref_user_data(hal);
255         if (user_data == NULL) {
256                 err("[VMODEM] User data is NULL");
257                 return TCORE_RETURN_FAILURE;
258         }
259
260         ret = vdpram_tty_write(user_data->vdpram_fd, data, data_len);
261         if(ret < 0)     {
262                 err("[VMODEM] Write failed");
263                 return TCORE_RETURN_FAILURE;
264         }
265         else {
266                 dbg("vdpram_tty_write success ret=%d (fd=%d, len=%d)", ret, user_data->vdpram_fd, data_len);
267                 return TCORE_RETURN_SUCCESS;
268         }
269 }
270
271 static TReturn hal_setup_netif(CoreObject *co,
272                                 TcoreHalSetupNetifCallback func,
273                                 void *user_data, unsigned int cid,
274                                 gboolean enable)
275 {
276         char ifname[DEVICE_NAME_LEN_MAX];
277         int size = 0;
278         int fd = 0;
279         char buf[32];
280         char *control = NULL;
281
282         if (cid > 3) {
283                 err("[VMODEM] Context ID: [%d]", cid);
284                 return TCORE_RETURN_EINVAL;
285         }
286
287         if (enable == TRUE) {
288                 dbg("[VMODEM] ACTIVATE - Context ID: [%d]", cid)
289                 control = "/sys/class/net/svnet0/pdp/activate";
290         } else {
291                 dbg("[VMODEM] DEACTIVATE - Context ID: [%d]", cid)
292                 control = "/sys/class/net/svnet0/pdp/deactivate";
293         }
294
295         fd = open(control, O_WRONLY);
296         if (fd < 0) {
297                 err("[VMODEM] Failed to Open interface: [%s]", control);
298
299                 /* Invoke callback function */
300                 if (func)
301                         func(co, -1, NULL, user_data);
302
303                 return TCORE_RETURN_FAILURE;
304         }
305
306         /* Context ID needs to be written to the Device */
307         snprintf(buf, sizeof(buf), "%d", cid);
308         size = write(fd, buf, strlen(buf));
309
310         /* Close 'fd' */
311         close(fd);
312
313         /* Device name */
314         snprintf(ifname, DEVICE_NAME_LEN_MAX, "%s%d", DEVICE_NAME_PREFIX, (cid - 1));
315         dbg("[VMODEM] Interface Name: [%s]", ifname);
316
317         /* Invoke callback function */
318         if (func)
319                 func(co, 0, ifname, user_data);
320
321         return TCORE_RETURN_SUCCESS;
322 }
323
324 /* HAL Operations */
325 static struct tcore_hal_operations hal_ops = {
326         .power = hal_power,
327         .send = hal_send,
328         .setup_netif = hal_setup_netif,
329 };
330
331 static gboolean on_load()
332 {
333         dbg("[VMODEM] Load!!!");
334
335         return TRUE;
336 }
337
338 static gboolean on_init(TcorePlugin *plugin)
339 {
340         TcoreHal *hal;
341         struct custom_data *data;
342
343         dbg("[VMODEM] Init!!!");
344
345         if (plugin == NULL) {
346                 err("[VMODEM] PLug-in is NULL");
347                 return FALSE;
348         }
349
350         /* Register Modem Interface Plug-in */
351         if (tcore_server_register_modem(tcore_plugin_ref_server(plugin), plugin)
352                                                                 == FALSE) {
353                 err("[VMODEM] Registration Failed");
354                 return FALSE;
355         }
356         dbg("[VMODEM] Registered from Server");
357
358         data = g_try_new0(struct custom_data, 1);
359         if (data == NULL) {
360                 err("[VMODEM] Failed to allocate memory for Custom data");
361
362                 /* Unregister from Server */
363                 tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), plugin);
364                 return FALSE;
365         }
366
367         /*
368          * Open DPRAM device
369          */
370         data->vdpram_fd = vdpram_open();
371
372         /*
373          * Create and initialize HAL
374          */
375         hal = tcore_hal_new(plugin, "vmodem", &hal_ops, TCORE_HAL_MODE_CUSTOM);
376         if (hal == NULL) {
377                 /* Close VDPRAM device */
378                 vdpram_close(data->vdpram_fd);
379
380                 /* Fre custom data */
381                 g_free(data);
382
383                 /* Unregister from Server */
384                 tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), plugin);
385
386                 return FALSE;
387         }
388
389         /* Set HAL as Modem Interface Plug-in's User data */
390         tcore_plugin_link_user_data(plugin, hal);
391
392         /* Link custom data to HAL user data */
393         tcore_hal_link_user_data(hal, data);
394
395         /* Register to Watch llist */
396         data->watch_id_vdpram = _register_gio_watch(hal,
397                                                                 data->vdpram_fd, on_recv_vdpram_message);
398         dbg("[VMODEM] fd: [%d] Watch ID: [%d]",
399                                                                 data->vdpram_fd, data->watch_id_vdpram);
400
401         /* Power ON VDPRAM device */
402         if (_modem_power(hal, TRUE) == TCORE_RETURN_SUCCESS) {
403                 dbg("[VMODEM] Power ON - [SUCCESS]");
404         } else {
405                 err("[VMODEM] Power ON - [FAIL]");
406                 goto EXIT;
407         }
408
409         /* Add Core Objects list to HAL */
410         _assign_objects_to_hal(hal);
411
412         /* Check CP Power ON */
413         g_timeout_add_full(G_PRIORITY_HIGH, SERVER_INIT_WAIT_TIMEOUT, _load_modem_plugin, hal, 0);
414
415         dbg("[VMMODEM] Exit");
416         return TRUE;
417
418 EXIT:
419         /* Deregister from Watch list */
420         _deregister_gio_watch(data->watch_id_vdpram);
421
422         /* Free HAL */
423         tcore_hal_free(hal);
424
425         /* Close VDPRAM device */
426         vdpram_close(data->vdpram_fd);
427
428         /* Free custom data */
429         g_free(data);
430
431         /* Unregister from Server */
432         tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), plugin);
433
434         return FALSE;
435 }
436
437 static void on_unload(TcorePlugin *plugin)
438 {
439         TcoreHal *hal;
440         struct custom_data *user_data;
441
442         dbg("[VMODEM] Unload!!!");
443
444         if (plugin == NULL)
445                 return;
446
447         hal = tcore_plugin_ref_user_data(plugin);
448         if (hal == NULL)
449                 return;
450
451         /* Unload Modem Plug-in */
452 #if 0   /* TODO - Open the code below */
453         tcore_server_unload_modem_plugin(tcore_plugin_ref_server(plugin), plugin);
454 #endif
455         user_data = tcore_hal_ref_user_data(hal);
456         if (user_data == NULL)
457                 return;
458
459         /* Deregister from Watch list */
460         _deregister_gio_watch(user_data->watch_id_vdpram);
461         dbg("[VMODEM] Deregistered Watch ID");
462
463         /* Free HAL */
464         tcore_hal_free(hal);
465         dbg("[VMODEM] Freed HAL");
466
467         /* Close VDPRAM device */
468         vdpram_close(user_data->vdpram_fd);
469         dbg("[VMODEM] Closed VDPRAM device");
470
471         /* Free custom data */
472         g_free(user_data);
473
474         tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), plugin);
475         dbg("[VMODEM] Unregistered from Server");
476
477         dbg("[VMODEM] Unloaded MODEM");
478 }
479
480 /* VMODEM Descriptor Structure */
481 struct tcore_plugin_define_desc plugin_define_desc = {
482         .name = "VMODEM",
483         .priority = TCORE_PLUGIN_PRIORITY_HIGH,
484         .version = 1,
485         .load = on_load,
486         .init = on_init,
487         .unload = on_unload
488 };