Patch consists of the following changes - 1. Removal of +XSIMSTATE subscription for...
[platform/core/telephony/tel-plugin-imc.git] / src / s_modem.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Harish Bishnoi <hbishnoi@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 #include <unistd.h>
25
26 #include <glib.h>
27
28 #include <tcore.h>
29 #include <hal.h>
30 #include <core_object.h>
31 #include <plugin.h>
32 #include <user_request.h>
33 #include <queue.h>
34 #include <co_modem.h>
35 #include <storage.h>
36 #include <server.h>
37 #include <at.h>
38 #include <mux.h>
39
40 #include "s_common.h"
41 #include "s_modem.h"
42
43
44 #define ID_RESERVED_AT 0x0229
45
46 #define MAX_VERSION_LEN 32
47 #define TAPI_MISC_ME_SN_LEN_MAX             32
48 #define TAPI_MISC_PRODUCT_CODE_LEN_MAX      32
49 #define TAPI_MISC_MODEL_ID_LEN_MAX          17
50 #define TAPI_MISC_PRL_ERI_VER_LEN_MAX       17
51
52 #define CPAS_RES_READY          0
53 #define CPAS_RES_UNAVAIL            1
54 #define CPAS_RES_UNKNOWN            2
55 #define CPAS_RES_RINGING            3
56 #define CPAS_RES_CALL_PROGRESS  4
57 #define CPAS_RES_ASLEEP           5
58 #define AT_VER_LEN 20
59
60
61 enum cp_state {
62         CP_STATE_OFFLINE,
63         CP_STATE_CRASH_RESET,
64         CP_STATE_CRASH_EXIT,
65         CP_STATE_BOOTING,
66         CP_STATE_ONLINE,
67         CP_STATE_NV_REBUILDING,
68         CP_STATE_LOADER_DONE,
69 };
70
71 typedef enum {
72         TAPI_MISC_ME_IMEI = 0x00, /**< 0x00: IMEI, GSM/UMTS device */
73         TAPI_MISC_ME_ESN = 0x01, /**< 0x01: ESN(Electronic Serial Number), It`s essentially run out. CDMA device */
74         TAPI_MISC_ME_MEID = 0x02, /**< 0x02: MEID, This value can have hexa decimal digits. CDMA device */
75         TAPI_MISC_ME_MAX = 0xff /**< 0xff: reserved */
76 } TelMiscSNIndexType_t;
77
78 typedef struct {
79         TelMiscSNIndexType_t sn_index; /**< serial number index */
80         int sn_len; /**< Length */
81         unsigned char szNumber[TAPI_MISC_ME_SN_LEN_MAX]; /**< Number */
82 } TelMiscSNInformation;
83
84 /**
85  * Mobile Equipment Version Information
86  */
87 typedef struct {
88         unsigned char ver_mask; /**< version mask  - 0x01:SW_ver, 0x02:HW_ver, 0x04:RF_CAL_date, 0x08:Product_code, 0x10:Model_ID, 0x20:PRL, 0x04:ERI, 0xff:all */
89         unsigned char szSwVersion[MAX_VERSION_LEN]; /**< Software version, null termination */
90         unsigned char szHwVersion[MAX_VERSION_LEN]; /**< Hardware version, null termination */
91         unsigned char szRfCalDate[MAX_VERSION_LEN]; /**< Calculation Date, null termination */
92         unsigned char szProductCode[TAPI_MISC_PRODUCT_CODE_LEN_MAX]; /**< product code, null termination */
93         unsigned char szModelId[TAPI_MISC_MODEL_ID_LEN_MAX]; /**< model id (only for CDMA), null termination */
94         unsigned char prl_nam_num; /**< number of PRL NAM fields */
95         unsigned char szPrlVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3]; /**< prl version (only for CDMA), null termination */
96         unsigned char eri_nam_num; /**< number of PRL NAM fields */
97         unsigned char szEriVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3]; /**< eri version (only for CDMA), null termination */
98 } TelMiscVersionInformation;
99
100
101 static void prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback);
102 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data);
103 static void on_response_network_registration(TcorePending *p, int data_len, const void *data, void *user_data);
104 static void on_response_enable_proactive_command(TcorePending *p, int data_len, const void *data, void *user_data);
105
106 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data)
107 {
108         dbg("on_confirmation_modem_message_send - msg out from queue.\n");
109
110         if (result == FALSE) {
111                 /* Fail */
112                 dbg("SEND FAIL");
113         } else {
114                 dbg("SEND OK");
115         }
116 }
117
118 static void on_response_enable_proactive_command(TcorePending *p, int data_len, const void *data, void *user_data)
119 {
120         const TcoreATResponse *resp = data;
121
122         if (resp->success > 0) {
123                 dbg("RESPONSE OK proactive command enabled");
124         } else {
125                 dbg("RESPONSE NOK proactive command disabled");
126         }
127 }
128
129 static void on_response_network_registration(TcorePending *p, int data_len, const void *data, void *user_data)
130 {
131         const TcoreATResponse *resp = data;
132
133         if (resp->success > 0) {
134                 dbg("registration attempt OK");
135         } else {
136                 dbg("registration attempt failed");
137         }
138 }
139
140 void prepare_and_send_pending_request(CoreObject *co, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
141 {
142         TcoreATRequest *req = NULL;
143         TcoreHal *hal = NULL;
144         TcorePending *pending = NULL;
145         TReturn ret;
146
147         hal = tcore_object_get_hal(co);
148         dbg("hal: %p", hal);
149
150         pending = tcore_pending_new(co, 0);
151         if (!pending)
152                 dbg("Pending is NULL");
153         req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
154
155         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
156
157         tcore_pending_set_request_data(pending, 0, req);
158         tcore_pending_set_response_callback(pending, callback, NULL);
159         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
160         ret = tcore_hal_send_request(hal, pending);
161 }
162
163 static void on_response_power_off(TcorePending *p, int data_len, const void *data, void *user_data)
164 {
165         CoreObject *o = 0;
166         TcoreHal *h = 0;
167
168         o = tcore_pending_ref_core_object(p);
169         h = tcore_object_get_hal(o);
170
171         dbg("modem power off");
172
173         tcore_hal_set_power_state(h, FALSE);
174 }
175
176 static void on_response_set_flight_mode(TcorePending *p, int data_len, const void *data, void *user_data)
177 {
178         CoreObject *o = NULL;
179         UserRequest *ur = NULL;
180         const TcoreATResponse *ATresp = data;
181         GSList *tokens = NULL;
182         const char *line = NULL;
183         struct tresp_modem_set_flightmode res = {0};
184         int response = 0;
185         struct tnoti_modem_flight_mode modem_flight_mode = {0};
186         const struct treq_modem_set_flightmode *req_data = NULL;
187
188         o = tcore_pending_ref_core_object(p);
189
190         if (ATresp->success > 0) {
191                 dbg("RESPONSE OK - flight mode operation finished");
192                 res.result = TCORE_RETURN_SUCCESS;
193         } else {
194                 dbg("RESPONSE NOK");
195                 line = (const char *) ATresp->final_response;
196                 tokens = tcore_at_tok_new(line);
197
198                 if (g_slist_length(tokens) < 1) {
199                         dbg("err cause not specified or string corrupted");
200                         res.result = TCORE_RETURN_3GPP_ERROR;
201                 } else {
202                         response = atoi(g_slist_nth_data(tokens, 0));
203                         /* TODO: CMEE error mapping is required. */
204                         res.result = TCORE_RETURN_3GPP_ERROR;
205                 }
206         }
207
208         ur = tcore_pending_ref_user_request(p);
209         if (NULL == ur) {
210                 dbg("No user request. Internal request created during boot-up sequence");
211
212                 if (ATresp->success > 0) {
213                         modem_flight_mode.enable = tcore_modem_get_flight_mode_state(o);
214                         dbg("sucess case - Sending Flight Mode Notification (%d) to Telephony Server", modem_flight_mode.enable);
215
216                         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_FLIGHT_MODE,
217                                                                                    sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode);
218                 }
219         } else {
220                 dbg("Sending response for Flight mode operation");
221
222                 req_data = tcore_user_request_ref_data(ur, NULL);
223
224                 if (TCORE_RETURN_SUCCESS == res.result) {
225                         if (TRUE == req_data->enable)
226                                 res.result = 1;
227                         else
228                                 res.result = 2;
229                 } else {
230                         res.result = 3;
231                 }
232
233                 tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE, sizeof(struct tresp_modem_set_flightmode), &res);
234
235                 if (req_data->enable == 0) {
236                         dbg("Flight mode is disabled, trigger COPS to register on network");
237                         /* Trigger Network registration (for the moment automatic) */
238                         prepare_and_send_pending_request(o, "AT+COPS=0", NULL, TCORE_AT_NO_RESULT, NULL);
239                 }
240         }
241
242         tcore_at_tok_free(tokens);
243 }
244
245 static void on_response_imei(TcorePending *p, int data_len, const void *data, void *user_data)
246 {
247         const TcoreATResponse *resp = data;
248         TcorePlugin *plugin = NULL;
249         struct tresp_modem_get_imei res;
250         TelMiscSNInformation *imei_property = NULL;
251         UserRequest *ur = NULL;
252         GSList *tokens = NULL;
253         const char *line;
254         int response = 0;
255
256         memset(&res, 0, sizeof(struct tresp_modem_get_imei));
257
258         if (resp->success > 0) {
259                 dbg("RESPONSE OK");
260                 if (resp->lines) {
261                         line = (const char *) resp->lines->data;
262                         tokens = tcore_at_tok_new(line);
263                         if (g_slist_length(tokens) != 1) {
264                                 msg("invalid message");
265                                 goto OUT;
266                         }
267                 }
268                 res.result = TCORE_RETURN_SUCCESS;
269                 strncpy(res.imei, g_slist_nth_data(tokens, 0), 16);
270
271                 dbg("imei = [%s]", res.imei);
272
273                 plugin = tcore_pending_ref_plugin(p);
274                 imei_property = tcore_plugin_ref_property(plugin, "IMEI");
275                 if (imei_property) {
276                         imei_property->sn_index = TAPI_MISC_ME_IMEI;
277                         imei_property->sn_len = strlen(res.imei);
278                         memcpy(imei_property->szNumber, res.imei, imei_property->sn_len);
279                 }
280         } else {
281                 dbg("RESPONSE NOK");
282                 if (resp->lines) {
283                         line = (const char *) resp->lines->data;
284                         tokens = tcore_at_tok_new(line);
285                 }
286
287
288                 if (g_slist_length(tokens) < 1) {
289                         dbg("err cause not specified or string corrupted");
290                         res.result = TCORE_RETURN_3GPP_ERROR;
291                 } else {
292                         response = atoi(g_slist_nth_data(tokens, 0));
293                         /* TODO: CMEE error mapping is required. */
294                         res.result = TCORE_RETURN_3GPP_ERROR;
295                 }
296         }
297
298         ur = tcore_pending_ref_user_request(p);
299         tcore_user_request_send_response(ur, TRESP_MODEM_GET_IMEI,
300                                         sizeof(struct tresp_modem_get_imei), &res);
301
302 OUT:
303         if (tokens != NULL)
304                 tcore_at_tok_free(tokens);
305
306         return;
307 }
308
309 static void on_response_version(TcorePending *p, int data_len, const void *data, void *user_data)
310 {
311         const TcoreATResponse *resp = data;
312         TcorePlugin *plugin = NULL;
313         struct tresp_modem_get_version res = {0};
314         TelMiscVersionInformation *vi_property = NULL;
315         TelMiscVersionInformation *vi = NULL;
316         UserRequest *ur = NULL;
317         GSList *tokens = NULL;
318         const char *line = NULL;
319         char *swver = NULL;
320         char *hwver = NULL;
321         char *caldate = NULL;
322         char *pcode = NULL;
323         char *id = NULL;
324
325         int response = 0;
326
327         if (resp->success > 0) {
328                 dbg("RESPONSE OK");
329                 if (resp->lines) {
330                         line = (const char *) resp->lines->data;
331                         tokens = tcore_at_tok_new(line);
332                         if (g_slist_length(tokens) == 1) {
333                                 swver = g_slist_nth_data(tokens, 0);
334                                 dbg("version: sw=[%s]", swver);
335                         } else if (g_slist_length(tokens) == 5) {
336                                 swver = g_slist_nth_data(tokens, 0);
337                                 hwver = g_slist_nth_data(tokens, 1);
338                                 caldate = g_slist_nth_data(tokens, 2);
339                                 pcode = g_slist_nth_data(tokens, 3);
340                                 id = g_slist_nth_data(tokens, 4);
341
342                                 dbg("version: sw=[%s], hw=[%s], rf_cal=[%s], product_code=[%s], model_id=[%s]",
343                                                                 swver, hwver, caldate, pcode, id);
344                         } else {
345                                 msg("invalid message");
346                                 goto OUT;
347                         }
348                 }
349
350                 vi = g_try_new0(TelMiscVersionInformation, 1);
351                 if (NULL != swver)
352                         memcpy(vi->szSwVersion, swver, strlen(swver));
353                 if (NULL != hwver)
354                         memcpy(vi->szHwVersion, hwver, strlen(hwver));
355                 if (NULL != caldate)
356                         memcpy(vi->szRfCalDate, caldate, strlen(caldate));
357                 if (NULL != pcode)
358                         memcpy(vi->szProductCode, pcode, strlen(pcode));
359                 if (NULL != id)
360                         memcpy(vi->szModelId, id, strlen(id));
361
362                 memset(&res, 0, sizeof(struct tresp_modem_get_version));
363
364                 if (NULL != swver) {
365                         snprintf(res.software,
366                                 (AT_VER_LEN > strlen(swver) ? strlen(swver) : AT_VER_LEN),
367                                 "%s", swver);
368                 }
369
370                 if (NULL != hwver) {
371                         snprintf(res.hardware,
372                                 (AT_VER_LEN > strlen(hwver) ? strlen(hwver) : AT_VER_LEN),
373                                 "%s", hwver);
374                 }
375
376                 plugin = tcore_pending_ref_plugin(p);
377                 vi_property = tcore_plugin_ref_property(plugin, "VERSION");
378                 memcpy(vi_property, vi, sizeof(TelMiscVersionInformation));
379                 free(vi);
380         } else {
381                 dbg("RESPONSE NOK");
382                 if (resp->lines) {
383                         line = (const char *) resp->lines->data;
384                         tokens = tcore_at_tok_new(line);
385                 }
386
387                 memset(&res, 0, sizeof(struct tresp_modem_get_version));
388
389
390                 if (g_slist_length(tokens) < 1) {
391                         dbg("err cause not specified or string corrupted");
392                         res.result = TCORE_RETURN_3GPP_ERROR;
393                 } else {
394                         response = atoi(g_slist_nth_data(tokens, 0));
395                         /* TODO: CMEE error mapping is required. */
396                         res.result = TCORE_RETURN_3GPP_ERROR;
397                 }
398         }
399
400         ur = tcore_pending_ref_user_request(p);
401         tcore_user_request_send_response(ur, TRESP_MODEM_GET_VERSION,
402                                                 sizeof(struct tresp_modem_get_version), &res);
403
404 OUT:
405         if (tokens != NULL)
406                 tcore_at_tok_free(tokens);
407
408         return;
409 }
410
411 static enum tcore_hook_return on_hook_sim_status(Server *s,
412                                 CoreObject *source, enum tcore_notification_command command,
413                                 unsigned int data_len, void *data, void *user_data)
414 {
415         TcorePlugin *plugin;
416         const struct tnoti_sim_status *noti_sim_status;
417         CoreObject *co_sat;
418         CoreObject *co_network;
419
420         plugin = tcore_object_ref_plugin(source);
421         co_sat = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SAT);
422         if (co_sat == NULL)
423                 return TCORE_HOOK_RETURN_CONTINUE;
424
425         co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK);
426         if (co_network == NULL)
427                 return TCORE_HOOK_RETURN_CONTINUE;
428
429         dbg("Get SIM status");
430         noti_sim_status = data;
431         if (noti_sim_status == NULL)
432                 return TCORE_HOOK_RETURN_CONTINUE;
433
434         /* If SIM is initialized, Enable STK and and attach to Network */
435         dbg("SIM Status: [%d]", noti_sim_status->sim_status);
436         if (noti_sim_status->sim_status == SIM_STATUS_INIT_COMPLETED) {
437                 dbg("SIM ready for attach!!! Enable STK and attach to Network");
438
439                 /* Sending AT+CFUN=6 */
440                 prepare_and_send_pending_request(co_sat, "AT+CFUN=6", NULL,
441                                                 TCORE_AT_NO_RESULT, on_response_enable_proactive_command);
442
443                 /* Sending AT+COPS */
444                 prepare_and_send_pending_request(co_network, "AT+COPS=0", NULL,
445                                                 TCORE_AT_NO_RESULT, on_response_network_registration);
446         }
447
448         return TCORE_HOOK_RETURN_CONTINUE;
449 }
450
451 gboolean modem_power_on(TcorePlugin *p)
452 {
453         CoreObject *co_modem = NULL;
454         struct treq_modem_set_flightmode flight_mode_set = {0};
455         struct tnoti_modem_power modem_power = {0};
456         Storage *strg = NULL;
457
458         co_modem = tcore_plugin_ref_core_object(p, CORE_OBJECT_TYPE_MODEM);
459         if (co_modem == NULL) {
460                 err("Modem Core object is NULL");
461                 return FALSE;
462         }
463
464         /* Set Modem Power State to 'ON' */
465         tcore_modem_set_powered(co_modem, TRUE);
466
467         /* Get Flight mode from VCONFKEY */
468         strg = tcore_server_find_storage(tcore_plugin_ref_server(p), "vconf");
469         flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE_BOOL);
470
471         /* Set Flight mode as per AP settings */
472         if (flight_mode_set.enable) {           /* Radio OFF */
473                 prepare_and_send_pending_request(co_modem, "AT+CFUN=4", NULL,
474                                                         TCORE_AT_NO_RESULT, on_response_set_flight_mode);
475
476                 /* Set Flight mode TRUE */
477                 tcore_modem_set_flight_mode_state(co_modem, TRUE);
478         } else {                                                        /* Radio ON */
479                 prepare_and_send_pending_request(co_modem, "AT+CFUN=1", NULL,
480                                                         TCORE_AT_NO_RESULT, on_response_set_flight_mode);
481
482                 /* Set Flight mode FALSE */
483                 tcore_modem_set_flight_mode_state(co_modem, FALSE);
484         }
485
486         /* Get IMEI */
487         prepare_and_send_pending_request(co_modem, "AT+CGSN", NULL,
488                                                         TCORE_AT_NUMERIC, on_response_imei);
489
490         /* Get Version Number  */
491         prepare_and_send_pending_request(co_modem, "AT+CGMR", NULL,
492                                                         TCORE_AT_SINGLELINE, on_response_version);
493
494         /* Send Notification to TAPI - MODEM_POWER */
495         modem_power.state = MODEM_STATE_ONLINE;
496
497         dbg("Sending notification - Modem Power state: [ONLINE]");
498         tcore_server_send_notification(tcore_plugin_ref_server(p),
499                 co_modem, TNOTI_MODEM_POWER, sizeof(modem_power), &modem_power);
500
501         return TRUE;
502 }
503
504 static TReturn power_off(CoreObject *o, UserRequest *ur)
505 {
506         TcoreHal *hal = NULL;
507         TcoreATRequest *req = NULL;
508         TcorePending *pending = NULL;
509
510         hal = tcore_object_get_hal(o);
511         pending = tcore_pending_new(o, 0);
512
513         req = tcore_at_request_new("AT+CFUN=0", NULL, TCORE_AT_NO_RESULT);
514
515         dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]",
516                                                 req->cmd, req->prefix, strlen(req->cmd));
517
518         tcore_pending_set_request_data(pending, 0, req);
519         tcore_pending_set_response_callback(pending, on_response_power_off, hal);
520         tcore_pending_link_user_request(pending, ur);
521         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
522
523         tcore_hal_send_request(hal, pending);
524
525         return TCORE_RETURN_SUCCESS;
526 }
527
528 static TReturn get_imei(CoreObject *o, UserRequest *ur)
529 {
530         TcoreHal *hal;
531         TcoreATRequest *req;
532         TcorePending *pending = NULL;
533
534         hal = tcore_object_get_hal(o);
535         if (FALSE == tcore_hal_get_power_state(hal)) {
536                 dbg("cp not ready/n");
537                 return TCORE_RETURN_ENOSYS;
538         }
539         pending = tcore_pending_new(o, 0);
540
541         req = tcore_at_request_new("AT+CGSN", NULL, TCORE_AT_NUMERIC);
542
543         dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]",
544                                                 req->cmd, req->prefix, strlen(req->cmd));
545
546         tcore_pending_set_request_data(pending, 0, req);
547         tcore_pending_set_response_callback(pending, on_response_imei, hal);
548         tcore_pending_link_user_request(pending, ur);
549         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
550
551         return tcore_hal_send_request(hal, pending);
552 }
553
554
555 static TReturn get_version(CoreObject *o, UserRequest *ur)
556 {
557         TcoreHal *hal;
558         TcoreATRequest *req;
559         TcorePending *pending = NULL;
560
561         hal = tcore_object_get_hal(o);
562         if (FALSE == tcore_hal_get_power_state(hal)) {
563                 dbg("cp not ready/n");
564                 return TCORE_RETURN_ENOSYS;
565         }
566         pending = tcore_pending_new(o, 0);
567
568         req = tcore_at_request_new("AT+CGMR", NULL, TCORE_AT_SINGLELINE);
569
570         dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]",
571                                                 req->cmd, req->prefix, strlen(req->cmd));
572
573         tcore_pending_set_request_data(pending, 0, req);
574         tcore_pending_set_response_callback(pending, on_response_version, hal);
575         tcore_pending_link_user_request(pending, ur);
576         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
577
578         return tcore_hal_send_request(hal, pending);
579 }
580
581 static TReturn set_flight_mode(CoreObject *o, UserRequest *ur)
582 {
583         TcoreHal *hal = NULL;
584         TcoreATRequest *req = NULL;
585         TcorePending *pending = NULL;
586         const struct treq_modem_set_flightmode *req_data = NULL;
587         char *cmd_str = NULL;
588
589         hal = tcore_object_get_hal(o);
590         if (FALSE == tcore_hal_get_power_state(hal)) {
591                 dbg("cp not ready/n");
592                 return TCORE_RETURN_ENOSYS;
593         }
594         pending = tcore_pending_new(o, 0);
595
596         req_data = tcore_user_request_ref_data(ur, NULL);
597
598         if (req_data->enable) {
599                 dbg("Flight mode on/n");
600                 cmd_str = g_strdup("AT+CFUN=4");
601         } else {
602                 dbg("Flight mode off/n");
603                 cmd_str = g_strdup("AT+CFUN=1");
604         }
605
606         req = tcore_at_request_new((const char *)cmd_str, NULL, TCORE_AT_NO_RESULT);
607         g_free(cmd_str);
608
609         dbg("Command: [%s], Prefix(if any): [%s], Command Length: [%d]",
610                                                 req->cmd, req->prefix, strlen(req->cmd));
611
612         tcore_pending_set_request_data(pending, 0, req);
613         tcore_pending_set_response_callback(pending, on_response_set_flight_mode, hal);
614         tcore_pending_link_user_request(pending, ur);
615         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
616
617         return tcore_hal_send_request(hal, pending);
618 }
619
620
621 static struct tcore_modem_operations modem_ops = {
622         .power_on = NULL,
623         .power_off = power_off,
624         .power_reset = NULL,
625         .set_flight_mode = set_flight_mode,
626         .get_imei = get_imei,
627         .get_version = get_version,
628         .get_sn = NULL,
629         .dun_pin_ctrl = NULL,
630 };
631
632 gboolean s_modem_init(TcorePlugin *cp, CoreObject *co_modem)
633 {
634         TelMiscVersionInformation *vi_property;
635         TelMiscSNInformation *imei_property;
636         TelMiscSNInformation *sn_property;
637
638         dbg("Enter");
639
640         tcore_modem_override_ops(co_modem, &modem_ops);
641
642         vi_property = g_try_new0(TelMiscVersionInformation, 1);
643         tcore_plugin_link_property(cp, "VERSION", vi_property);
644
645         imei_property = g_try_new0(TelMiscSNInformation, 1);
646         tcore_plugin_link_property(cp, "IMEI", imei_property);
647
648         sn_property = g_try_new0(TelMiscSNInformation, 1);
649         tcore_plugin_link_property(cp, "SN", sn_property);
650
651         tcore_server_add_notification_hook(tcore_plugin_ref_server(cp),
652                                                         TNOTI_SIM_STATUS, on_hook_sim_status, NULL);
653
654         dbg("Exit");
655         return TRUE;
656 }
657
658 void s_modem_exit(TcorePlugin *cp, CoreObject *co_modem)
659 {
660         TelMiscVersionInformation *vi_property;
661         TelMiscSNInformation *imei_property;
662         TelMiscSNInformation *sn_property;
663         TcorePlugin *plugin = tcore_object_ref_plugin(co_modem);
664
665         vi_property = tcore_plugin_ref_property(plugin, "VERSION");
666         g_free(vi_property);
667
668         imei_property = tcore_plugin_ref_property(plugin, "IMEI");
669         g_free(imei_property);
670
671         sn_property = tcore_plugin_ref_property(plugin, "SN");
672         g_free(sn_property);
673
674         dbg("Exit");
675 }