Initial refactoring merge
[platform/core/telephony/tel-plugin-vmodem.git] / src / desc-vmodem.c
1 /*
2  * tel-plugin-vmodem
3  *
4  * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <pthread.h>
23 #include <unistd.h>
24 #include <time.h>
25 #include <fcntl.h>
26
27 #include <glib.h>
28
29 #include <tcore.h>
30 #include <server.h>
31 #include <plugin.h>
32 #include <hal.h>
33
34 #include "config.h"
35 #include "vdpram.h"
36 #include "vdpram_dump.h"
37
38 #define VMODEM_HAL_NAME         "vmodem"
39
40 #define DEVICE_NAME_LEN_MAX             16
41 #define DEVICE_NAME_PREFIX              "pdp"
42
43 #define BUF_LEN_MAX                     512
44
45 #define AT_CP_POWER_ON_TIMEOUT  500
46
47 static guint __register_gio_watch(TcoreHal *h, int fd, void *callback)
48 {
49         GIOChannel *channel = NULL;
50         guint source;
51
52         dbg("Register to Watch list - fd: [%d]", fd);
53
54         if ((fd < 0) || (callback == NULL))
55                 return 0;
56
57         channel = g_io_channel_unix_new(fd);
58         source = g_io_add_watch(channel, G_IO_IN, (GIOFunc) callback, h);
59         g_io_channel_unref(channel);
60         channel = NULL;
61
62         return source;
63 }
64
65 static void __deregister_gio_watch(guint watch_id)
66 {
67         dbg("Deregister Watch ID: [%d]", watch_id);
68
69         /* Remove source */
70         g_source_remove(watch_id);
71 }
72
73 static TcoreHookReturn __on_hal_send(TcoreHal *hal,
74                 guint data_len, void *data, void *user_data)
75 {
76         /* Dumping Send (Write) data */
77         vdpram_hex_dump(TRUE, data_len, data);
78
79         return TCORE_HOOK_RETURN_CONTINUE;
80 }
81
82 static void __on_hal_recv(TcoreHal *hal,
83         guint data_len, const void *data, void *user_data)
84 {
85         /* Dumping Receive (Read) data */
86         vdpram_hex_dump(FALSE, data_len, (void *)data);
87 }
88
89 static gboolean __modem_power(TcoreHal *hal, gboolean enable)
90 {
91         CustomData *user_data;
92
93         user_data = tcore_hal_ref_user_data(hal);
94         if (user_data == NULL) {
95                 err("User data is NULL");
96                 return FALSE;
97         }
98
99         if (enable == TRUE) {           /* POWER ON */
100                 if (FALSE == vdpram_poweron(user_data->vdpram_fd)) {
101                         err("Power ON - [FAIL]");
102                         return FALSE;
103                 }
104
105                 /* Set Power State - ON */
106                 tcore_hal_set_power_state(hal, TRUE);
107         } else {                                /* POWER OFF */
108                 if (vdpram_poweroff(user_data->vdpram_fd) == FALSE) {
109                         err("Power OFF - [FAIL]");
110                         return FALSE;
111                 }
112
113                 /* Set Power state - OFF */
114                 tcore_hal_set_power_state(hal, FALSE);
115         }
116
117         return TRUE;
118 }
119
120 static gboolean __on_recv_vdpram_message(GIOChannel *channel,
121         GIOCondition condition, gpointer data)
122 {
123         TcoreHal *hal = data;
124         CustomData *custom;
125         char buf[BUF_LEN_MAX] = {0, };
126         int n = 0;
127         TelReturn ret;
128
129         custom = tcore_hal_ref_user_data(hal);
130         memset(buf, 0x0, BUF_LEN_MAX);
131
132         /* Read from Device */
133         n = vdpram_tty_read(custom->vdpram_fd, buf, BUF_LEN_MAX);
134         if (n < 0) {
135                 err("Read error - Data received: [%d]", n);
136                 return TRUE;
137         }
138         dbg("DPRAM Receive - Data length: [%d]", n);
139
140         /* Emit receive callback */
141
142
143         msg("\n---------- [RECV] Length of received data: [%d] ----------\n", n);
144
145         /* Emit response callback */
146         tcore_hal_emit_recv_callback(hal, n, buf);
147
148         /* Dispatch received data to response handler */
149         ret = tcore_hal_dispatch_response_data(hal, 0, n, buf);
150         msg("\n---------- [RECV FINISH] Receive processing: [%d] ----------\n", ret);
151
152         return TRUE;
153 }
154
155 static gboolean __power_on(gpointer data)
156 {
157         CustomData *user_data;
158         TcoreHal *hal = (TcoreHal*)data;
159
160         dbg("Entry");
161
162         user_data = tcore_hal_ref_user_data(hal);
163         tcore_check_return_value_assert(user_data != NULL, TRUE);
164
165         /*
166          * Open DPRAM device: Create and Open interface to CP
167          */
168         user_data->vdpram_fd = vdpram_open();
169         if (user_data->vdpram_fd < 1) {
170                 TcorePlugin *plugin = tcore_hal_ref_plugin(hal);
171                 Server *server = tcore_plugin_ref_server(plugin);
172
173                 err("Failed to Create/Open CP interface");
174
175                 /* Notify server a modem error occured */
176                 tcore_server_send_server_notification(server,
177                         TCORE_SERVER_NOTIFICATION_MODEM_ERR, 0, NULL);
178
179                 goto EXIT;
180         }
181         dbg("Created AP-CP interface");
182
183         /* Register to Watch llist */
184         user_data->vdpram_watch_id = __register_gio_watch(hal,
185                                 user_data->vdpram_fd, __on_recv_vdpram_message);
186         dbg("fd: [%d] Watch ID: [%d]", user_data->vdpram_fd, user_data->vdpram_watch_id);
187
188         /* Power ON VDPRAM device */
189         if (__modem_power(hal, TRUE)) {
190                 dbg("Power ON - [SUCCESS]");
191         } else {
192                 err("Power ON - [FAIL]");
193                 goto EXIT;
194         }
195
196         /* CP is ONLINE, send AT+CPAS */
197         vmodem_config_check_cp_power(hal);
198
199         /* To stop the cycle need to return FALSE */
200         return FALSE;
201
202 EXIT:
203         /* TODO: Handle Deregister */
204
205         /* To stop the cycle need to return FALSE */
206         return FALSE;
207 }
208
209 /* HAL Operations */
210 static TelReturn _hal_power(TcoreHal *hal, gboolean flag)
211 {
212         return __modem_power(hal, flag);
213 }
214
215 static TelReturn _hal_send(TcoreHal *hal,
216         guint data_len, void *data)
217 {
218         CustomData *user_data;
219         gint ret;
220
221         if (tcore_hal_get_power_state(hal) == FALSE) {
222                 err("HAL Power state - OFF");
223                 return TEL_RETURN_FAILURE;
224         }
225
226         user_data = tcore_hal_ref_user_data(hal);
227         if (user_data == NULL) {
228                 err("User data is NULL");
229                 return TEL_RETURN_FAILURE;
230         }
231
232         ret = vdpram_tty_write(user_data->vdpram_fd, data, data_len);
233         if(ret < 0) {
234                 err("Write failed");
235                 return TEL_RETURN_FAILURE;
236         }
237         dbg("vdpram_tty_write success ret=%d (fd=%d, len=%d)",
238                 ret, user_data->vdpram_fd, data_len);
239
240         return TEL_RETURN_SUCCESS;
241 }
242
243 static TelReturn _hal_setup_netif(CoreObject *co,
244         TcoreHalSetupNetifCallback func, void *user_data,
245         guint cid, gboolean enable)
246 {
247         char ifname[DEVICE_NAME_LEN_MAX];
248         int size = 0;
249         int fd = 0;
250         char buf[32];
251         char *control = NULL;
252
253         if (cid > 3) {
254                 err("Context ID: [%d]", cid);
255                 return TEL_RETURN_INVALID_PARAMETER;
256         }
257
258         if (enable == TRUE) {
259                 dbg("ACTIVATE - Context ID: [%d]", cid);
260                 control = "/sys/class/net/svnet0/pdp/activate";
261         } else {
262                 dbg("DEACTIVATE - Context ID: [%d]", cid);
263                 control = "/sys/class/net/svnet0/pdp/deactivate";
264         }
265
266         fd = open(control, O_WRONLY);
267         if (fd < 0) {
268                 err("Failed to Open interface: [%s]", control);
269
270                 /* Invoke callback function */
271                 if (func)
272                         func(co, -1, NULL, user_data);
273
274                 return TEL_RETURN_FAILURE;
275         }
276
277         /* Context ID needs to be written to the Device */
278         snprintf(buf, sizeof(buf), "%d", cid);
279         size = write(fd, buf, strlen(buf));
280
281         /* Close 'fd' */
282         close(fd);
283
284         /* Device name */
285         snprintf(ifname, DEVICE_NAME_LEN_MAX, "%s%d", DEVICE_NAME_PREFIX, (cid - 1));
286         dbg("Interface Name: [%s]", ifname);
287
288         /* Invoke callback function */
289         if (func)
290                 func(co, 0, ifname, user_data);
291
292         return TEL_RETURN_SUCCESS;
293 }
294
295 /* HAL Operations */
296 static TcoreHalOperations hal_ops = {
297         .power = _hal_power,
298         .send = _hal_send,
299         .setup_netif = _hal_setup_netif,
300 };
301
302 static gboolean on_load()
303 {
304         dbg("Load!!!");
305
306         return TRUE;
307 }
308
309 static gboolean on_init(TcorePlugin *plugin)
310 {
311         TcoreHal *hal;
312         CustomData *data;
313         dbg("Init!!!");
314
315         tcore_check_return_value_assert(plugin != NULL, FALSE);
316
317         /* Custom data for Modem Interface Plug-in */
318         data = tcore_malloc0(sizeof(CustomData));
319         dbg("Created custom data memory");
320
321         /* Create Physical HAL */
322         hal = tcore_hal_new(plugin, VMODEM_HAL_NAME,
323                         &hal_ops, TCORE_HAL_MODE_AT);
324         if (hal == NULL) {
325                 err("Failed to Create Physical HAL");
326                 tcore_free(data);
327                 return FALSE;
328         }
329         dbg("HAL [0x%x] created", hal);
330
331         /* Set HAL as Modem Interface Plug-in's User data */
332         tcore_plugin_link_user_data(plugin, hal);
333
334         /* Link Custom data to HAL's 'user_data' */
335         tcore_hal_link_user_data(hal, data);
336
337         /* Add callbacks for Send/Receive Hooks */
338         tcore_hal_add_send_hook(hal, __on_hal_send, NULL);
339         tcore_hal_add_recv_callback(hal, __on_hal_recv, NULL);
340         dbg("Added Send hook and Receive callback");
341
342         /* Set HAL state to Power OFF (FALSE) */
343         (void)tcore_hal_set_power_state(hal, FALSE);
344         dbg("HAL Power State: Power OFF");
345
346         /* Resgister to Server */
347         if (tcore_server_register_modem(tcore_plugin_ref_server(plugin),
348                 plugin) == FALSE) {
349                 err("Registration Failed");
350
351                 tcore_hal_free(hal);
352                 tcore_free(data);
353                 return FALSE;
354         }
355         dbg("Registered from Server");
356
357         /* Check CP Power ON */
358         g_timeout_add_full(G_PRIORITY_HIGH,
359                 AT_CP_POWER_ON_TIMEOUT, __power_on, hal, NULL);
360
361         return TRUE;
362 }
363
364 static void on_unload(TcorePlugin *plugin)
365 {
366         TcoreHal *hal;
367         CustomData *user_data;
368         dbg("Unload!!!");
369
370         tcore_check_return_assert(plugin != NULL);
371
372         /* Unload Modem Plug-in */
373         tcore_server_unload_modem_plugin(tcore_plugin_ref_server(plugin), plugin);
374
375         /* Unregister Modem Interface Plug-in from Server */
376         tcore_server_unregister_modem(tcore_plugin_ref_server(plugin), plugin);
377         dbg("Unregistered from Server");
378
379         /* HAL cleanup */
380         hal = tcore_plugin_ref_user_data(plugin);
381         if (hal == NULL) {
382                 err("HAL is NULL");
383                 return;
384         }
385
386         user_data = tcore_hal_ref_user_data(hal);
387         if (user_data == NULL)
388                 return;
389
390         /* Deregister from Watch list */
391         __deregister_gio_watch(user_data->vdpram_watch_id);
392         dbg("Deregistered Watch ID");
393
394         /* Close VDPRAM device */
395         (void)vdpram_close(user_data->vdpram_fd);
396         dbg("Closed VDPRAM device");
397
398         /* Free custom data */
399         g_free(user_data);
400
401         /* Free HAL */
402         tcore_hal_free(hal);
403         dbg("Freed HAL");
404
405         dbg("Unloaded MODEM Interface Plug-in");
406 }
407
408 /* VMODEM (Modem Interface Plug-in) descriptor */
409 EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
410         .name = "vmodem",
411         .priority = TCORE_PLUGIN_PRIORITY_HIGH,
412         .version = 1,
413         .load = on_load,
414         .init = on_init,
415         .unload = on_unload
416 };