Initialize Tizen 2.3
[framework/system/deviced.git] / src / telephony / telephony.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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
20 #include <ITapiModem.h>
21 #include <TelPower.h>
22 #include <tapi_event.h>
23 #include <tapi_common.h>
24 #include <TapiCommon.h>
25 #include <TapiEvent.h>
26 #include <ITapiProductivity.h>
27
28 #include <unistd.h>
29 #include <assert.h>
30 #include <vconf.h>
31
32 #include <device-node.h>
33 #include "dd-deviced.h"
34 #include "core/log.h"
35 #include "core/queue.h"
36 #include "core/predefine.h"
37 #include "core/data.h"
38 #include "core/common.h"
39 #include "core/devices.h"
40 #include "core/edbus-handler.h"
41 #include "display/core.h"
42 #include "power/power-handler.h"
43
44 #define PREDEF_FLIGHT_MODE      "flightmode"
45 #define PREDEF_ENTERSLEEP       "entersleep"
46 #define PREDEF_LEAVESLEEP       "leavesleep"
47
48 #define POWER_RESTART           5
49
50 static TapiHandle *tapi_handle = NULL;
51 static Ecore_Timer *poweroff_timer_id = NULL;
52 static int reboot_opt;
53
54 static Eina_Bool telephony_powerdown_ap_internal(void *data)
55 {
56         powerdown_ap(data);
57         return EINA_FALSE;
58 }
59 static void telephony_powerdown_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
60 {
61         telephony_powerdown_ap_internal(data);
62 }
63
64 static void telephony_restart_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
65 {
66         restart_ap((void *)reboot_opt);
67 }
68
69 static Eina_Bool telephony_restart_ap_by_force(void *data)
70 {
71         if (poweroff_timer_id) {
72                 ecore_timer_del(poweroff_timer_id);
73                 poweroff_timer_id = NULL;
74         }
75         restart_ap(data);
76         return EINA_TRUE;
77 }
78
79 static void powerdown_res_cb(TapiHandle *handle, int result, void *data, void *user_data)
80 {
81         _D("poweroff command request : %d",result);
82 }
83
84 static Eina_Bool telephony_powerdown_ap_by_force(void *data)
85 {
86         if (poweroff_timer_id) {
87                 ecore_timer_del(poweroff_timer_id);
88                 poweroff_timer_id = NULL;
89         }
90         powerdown_ap(data);
91         return EINA_TRUE;
92 }
93
94 static int telephony_start(void)
95 {
96         int ready = 0;
97
98         if (tapi_handle) {
99                 _I("already initialized");
100                 return 0;
101         }
102         if (vconf_get_bool(VCONFKEY_TELEPHONY_READY,&ready) != 0 || ready != 1) {
103                 _E("fail to get %s(%d)", VCONFKEY_TELEPHONY_READY, ready);
104                 return -EINVAL;
105         }
106         tapi_handle = tel_init(NULL);
107         if (tapi_handle == NULL) {
108                 _E("tapi init error");
109                 return -EINVAL;
110         }
111         return 0;
112 }
113
114 static int telephony_stop(void)
115 {
116         int ret;
117         tel_deregister_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER);
118         ret = tel_deinit(tapi_handle);
119         if (ret != 0) {
120                 _E("fail to deinit");
121                 return -EINVAL;
122         }
123         tapi_handle = NULL;
124         return 0;
125 }
126
127 static void telephony_exit(void *data)
128 {
129         int ret;
130
131         if (!data) {
132                 _E("Option Failed");
133                 return;
134         }
135
136         if (!strncmp(data, PREDEF_POWEROFF, strlen(PREDEF_POWEROFF))) {
137                 _I("Terminate");
138                 ret = tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER,
139                                 telephony_powerdown_ap, NULL);
140                 if (ret != TAPI_API_SUCCESS) {
141                         _E("tel_register_event is not subscribed. error %d", ret);
142                         telephony_powerdown_ap_by_force(NULL);
143                         return;
144                 }
145                 ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF,
146                                 powerdown_res_cb, NULL);
147                 if (ret != TAPI_API_SUCCESS) {
148                         _E("tel_process_power_command() error %d\n", ret);
149                         telephony_powerdown_ap_by_force(NULL);
150                         return;
151                 }
152                 poweroff_timer_id = ecore_timer_add(15,
153                     telephony_powerdown_ap_internal, NULL);
154                 return;
155         }
156
157         if (strncmp(data, PREDEF_REBOOT, strlen(PREDEF_REBOOT)) &&
158             strncmp(data, PREDEF_RECOVERY, strlen(PREDEF_RECOVERY)) &&
159             strncmp(data, PREDEF_FOTA_REBOOT, strlen(PREDEF_FOTA_REBOOT))) {
160                 _E("Fail %s", data);
161                 return;
162         }
163
164         _I("Option: %s", data);
165          if (!strncmp(data, PREDEF_RECOVERY, strlen(PREDEF_RECOVERY)))
166                 reboot_opt = SYSTEMD_STOP_POWER_RESTART_RECOVERY;
167         else if (!strncmp(data, PREDEF_REBOOT, strlen(PREDEF_REBOOT)))
168                 reboot_opt = SYSTEMD_STOP_POWER_RESTART;
169         else if (!strncmp(data, PREDEF_FOTA_REBOOT, strlen(PREDEF_FOTA_REBOOT)))
170                 reboot_opt = SYSTEMD_STOP_POWER_RESTART_FOTA;
171
172         ret = tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER,
173                         telephony_restart_ap, NULL);
174         if (ret != TAPI_API_SUCCESS) {
175                 _E("tel_register_event is not subscribed. error %d", ret);
176                 telephony_restart_ap_by_force((void *)POWER_RESTART);
177                 return;
178         }
179         ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF,
180                         powerdown_res_cb, NULL);
181         if (ret != TAPI_API_SUCCESS) {
182                 _E("tel_process_power_command() error %d", ret);
183                 telephony_restart_ap_by_force((void *)reboot_opt);
184                 return;
185         }
186         poweroff_timer_id = ecore_timer_add(15,telephony_restart_ap_by_force,
187                                                         (void *)reboot_opt);
188 }
189
190 static void telephony_flight_mode_on(TapiHandle *handle, int result, void *data, void *user_data)
191 {
192         int ret;
193         int bCurFlightMode = 0;
194
195         if (result != TAPI_POWER_FLIGHT_MODE_ENTER) {
196                 _E("flight mode enter failed %d", result);
197                 return;
198         }
199         _D("enter flight mode result : %d", result);
200         ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &bCurFlightMode);
201         if (ret == 0)
202                 _D("Flight Mode is %d", bCurFlightMode);
203         else
204                 _E("failed to get vconf key");
205 }
206
207 static void telephony_flight_mode_off(TapiHandle *handle, int result, void *data, void *user_data)
208 {
209         int ret;
210         int bCurFlightMode = 0;
211
212         if (result != TAPI_POWER_FLIGHT_MODE_LEAVE) {
213                 _E("flight mode leave failed %d", result);
214                 return;
215         }
216         _D("leave flight mode result : %d", result);
217         ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &bCurFlightMode);
218         if (ret == 0)
219                 _D("Flight Mode is %d", bCurFlightMode);
220         else
221                 _E("failed to get vconf key");
222 }
223
224 static int telephony_flight_mode(int argc, char **argv)
225 {
226         int ret;
227         int mode;
228         int err = TAPI_API_SUCCESS;
229
230         if (argc != 1 || argv[0] == NULL) {
231                 _E("FlightMode Set predefine action failed");
232                 return -1;
233         }
234         mode = atoi(argv[0]);
235
236         if (tapi_handle == NULL) {
237                 ret = telephony_start();
238                 if (ret != 0) {
239                         _E("fail to get tapi handle");
240                         return -1;
241                 }
242         }
243
244         if (mode == 1) {
245                 err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE,
246                                 telephony_flight_mode_off, NULL);
247         } else if (mode == 0) {
248                 err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER,
249                                 telephony_flight_mode_on, NULL);
250         }
251         if (err != TAPI_API_SUCCESS)
252                 _E("FlightMode tel api action failed %d",err);
253
254         return 0;
255 }
256
257 static int telephony_enter_sleep(int argc, char **argv)
258 {
259         int ret;
260
261         pm_change_internal(getpid(), LCD_NORMAL);
262         sync();
263
264         /* flight mode
265          * TODO - add check, cb, etc...
266          * should be checked wirh telephony part */
267         ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER,
268                         telephony_flight_mode_on, NULL);
269         _I("request for changing into flight mode : %d", ret);
270
271         launch_evenif_exist("/etc/rc.d/rc.entersleep", "");
272         pm_change_internal(getpid(), POWER_OFF);
273
274         return 0;
275 }
276
277 static int telephony_leave_sleep(int argc, char **argv)
278 {
279         int ret;
280
281         pm_change_internal(getpid(), LCD_NORMAL);
282         sync();
283
284         /* flight mode
285          * TODO - add check, cb, etc...
286          * should be checked wirh telephony part */
287         ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE,
288                         telephony_flight_mode_off, NULL);
289         _I("request for changing into flight mode : %d", ret);
290
291         return 0;
292 }
293
294 static DBusMessage *flight_mode_handler(E_DBus_Object *obj, DBusMessage *msg)
295 {
296         DBusError err;
297         DBusMessageIter iter;
298         DBusMessage *reply;
299         pid_t pid;
300         int ret;
301         int argc;
302         char *type_str;
303         char *argv;
304
305         dbus_error_init(&err);
306
307         if (!dbus_message_get_args(msg, &err,
308                     DBUS_TYPE_STRING, &type_str,
309                     DBUS_TYPE_INT32, &argc,
310                     DBUS_TYPE_STRING, &argv, DBUS_TYPE_INVALID)) {
311                 _E("there is no message");
312                 ret = -EINVAL;
313                 goto out;
314         }
315
316         if (argc < 0) {
317                 _E("message is invalid!");
318                 ret = -EINVAL;
319                 goto out;
320         }
321
322         pid = get_edbus_sender_pid(msg);
323         if (kill(pid, 0) == -1) {
324                 _E("%d process does not exist, dbus ignored!", pid);
325                 ret = -ESRCH;
326                 goto out;
327         }
328
329         telephony_flight_mode(argc, (char **)&argv);
330
331 out:
332         reply = dbus_message_new_method_return(msg);
333         dbus_message_iter_init_append(reply, &iter);
334         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
335
336         return reply;
337 }
338
339 static DBusMessage *telephony_handler(E_DBus_Object *obj, DBusMessage *msg)
340 {
341         DBusError err;
342         DBusMessageIter iter;
343         DBusMessage *reply;
344         pid_t pid;
345         int ret;
346         int argc;
347         char *type_str;
348
349         dbus_error_init(&err);
350
351         if (!dbus_message_get_args(msg, &err,
352                     DBUS_TYPE_STRING, &type_str,
353                     DBUS_TYPE_INT32, &argc, DBUS_TYPE_INVALID)) {
354                 _E("there is no message");
355                 ret = -EINVAL;
356                 goto out;
357         }
358
359         if (argc < 0) {
360                 _E("message is invalid!");
361                 ret = -EINVAL;
362                 goto out;
363         }
364
365         pid = get_edbus_sender_pid(msg);
366         if (kill(pid, 0) == -1) {
367                 _E("%d process does not exist, dbus ignored!", pid);
368                 ret = -ESRCH;
369                 goto out;
370         }
371
372         if (tapi_handle == NULL) {
373                 if (telephony_start() != 0)
374                         _E("fail to get tapi handle");
375         }
376
377         if (!strncmp(type_str, PREDEF_ENTERSLEEP, strlen(PREDEF_ENTERSLEEP)))
378                 ret = telephony_enter_sleep(0, NULL);
379         else if (!strncmp(type_str, PREDEF_LEAVESLEEP, strlen(PREDEF_LEAVESLEEP)))
380                 ret = telephony_leave_sleep(0, NULL);
381
382 out:
383         reply = dbus_message_new_method_return(msg);
384         dbus_message_iter_init_append(reply, &iter);
385         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
386
387         return reply;
388 }
389
390 static const struct edbus_method edbus_methods[] = {
391         { PREDEF_FLIGHT_MODE, "sis", "i", flight_mode_handler },
392         { PREDEF_ENTERSLEEP, "si", "i", telephony_handler },
393         { PREDEF_LEAVESLEEP, "si", "i", telephony_handler },
394         /* Add methods here */
395 };
396
397 static void telephony_init(void *data)
398 {
399         int ret;
400
401         /* init dbus interface */
402         ret = register_edbus_method(DEVICED_PATH_POWER, edbus_methods,
403                         ARRAY_SIZE(edbus_methods));
404         if (ret < 0)
405                 _E("fail to init edbus method(%d)", ret);
406
407         register_action(PREDEF_FLIGHT_MODE, telephony_flight_mode, NULL, NULL);
408         register_action(PREDEF_ENTERSLEEP, telephony_enter_sleep, NULL, NULL);
409         register_action(PREDEF_LEAVESLEEP, telephony_leave_sleep, NULL, NULL);
410 }
411
412 static const struct device_ops tel_device_ops = {
413         .priority       = DEVICE_PRIORITY_NORMAL,
414         .name           = "telephony",
415         .init           = telephony_init,
416         .start          = telephony_start,
417         .stop           = telephony_stop,
418         .exit           = telephony_exit,
419 };
420
421 DEVICE_OPS_REGISTER(&tel_device_ops)