Revert manifest to default one
[profile/ivi/tel-plugin-atmodem.git] / src / s_modem.c
1 /*
2  * tel-plugin-atmodem
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hayoon Ko <hayoon.ko@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 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <glib.h>
25
26 #include <tcore.h>
27 #include <hal.h>
28 #include <core_object.h>
29 #include <plugin.h>
30 #include <queue.h>
31 #include <co_modem.h>
32 #include <storage.h>
33 #include <server.h>
34
35 #include "s_common.h"
36 #include "s_modem.h"
37
38 #include "atchannel.h"
39 #include "at_tok.h"
40
41 #define MAX_VERSION_LEN 32
42 #define TAPI_MISC_ME_SN_LEN_MAX                         32
43 #define TAPI_MISC_PRODUCT_CODE_LEN_MAX          32
44 #define TAPI_MISC_MODEL_ID_LEN_MAX                      17
45 #define TAPI_MISC_PRL_ERI_VER_LEN_MAX           17
46
47 enum cp_state {
48         CP_STATE_OFFLINE,
49         CP_STATE_CRASH_RESET,
50         CP_STATE_CRASH_EXIT,
51         CP_STATE_BOOTING,
52         CP_STATE_ONLINE,
53         CP_STATE_NV_REBUILDING,
54         CP_STATE_LOADER_DONE,
55 };
56
57
58 enum TelMiscSNIndexType_t{
59         TAPI_MISC_ME_IMEI = 0x00, /**< 0x00: IMEI, GSM/UMTS device */
60         TAPI_MISC_ME_ESN = 0x01, /**< 0x01: ESN(Electronic Serial Number), It`s essentially run out. CDMA device */
61         TAPI_MISC_ME_MEID = 0x02, /**< 0x02: MEID, This value can have hexa decimal digits. CDMA device */
62         TAPI_MISC_ME_MAX = 0xff /**< 0xff: reserved */
63 };
64
65 struct TelMiscSNInformation{
66         enum TelMiscSNIndexType_t sn_index; /**< serial number index */
67         int sn_len; /**< Length */
68         unsigned char szNumber[TAPI_MISC_ME_SN_LEN_MAX]; /**< Number */
69 };
70
71 /**
72  * Mobile Equipment Version Information
73  */
74 struct TelMiscVersionInformation{
75         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 */
76         unsigned char szSwVersion[MAX_VERSION_LEN]; /**< Software version, null termination */
77         unsigned char szHwVersion[MAX_VERSION_LEN]; /**< Hardware version, null termination */
78         unsigned char szRfCalDate[MAX_VERSION_LEN]; /**< Calculation Date, null termination */
79         unsigned char szProductCode[TAPI_MISC_PRODUCT_CODE_LEN_MAX]; /**< product code, null termination */
80         unsigned char szModelId[TAPI_MISC_MODEL_ID_LEN_MAX]; /**< model id (only for CDMA), null termination */
81         unsigned char prl_nam_num; /**< number of PRL NAM fields */
82         unsigned char szPrlVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3];/**< prl version (only for CDMA), null termination */
83         unsigned char eri_nam_num; /**< number of PRL NAM fields */
84         unsigned char szEriVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3];/**< eri version (only for CDMA), null termination */
85 };
86
87 extern struct ATResponse *sp_response;
88 extern char *s_responsePrefix;
89 extern enum ATCommandType s_type;
90
91 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data ); // from Kernel
92
93 static void on_confirmation_modem_message_send( TcorePending *p, gboolean result, void *user_data )
94 {
95         UserRequest* ur = NULL;
96         struct ATReqMetaInfo* metainfo = NULL;
97         unsigned int info_len =0;
98         dbg("on_confirmation_modem_message_send - msg out from queue. alloc ATRsp buffer & write rspPrefix if needed\n");
99
100         ReleaseResponse(); // release leftover
101 //alloc new sp_response
102         sp_response = at_response_new();
103
104
105         ur = tcore_pending_ref_user_request(p);
106         metainfo = (struct ATReqMetaInfo*)tcore_user_request_ref_metainfo(ur,&info_len);
107
108         if((metainfo->type == SINGLELINE)||
109                 (metainfo->type == MULTILINE))
110         {
111                 //cp rsp prefix
112                 s_responsePrefix = strdup(metainfo->responsePrefix);
113                 dbg("duplicating responsePrefix : %s\n", s_responsePrefix);
114         }
115         else
116         {
117                 s_responsePrefix = NULL;
118         }
119
120 //set atcmd type into s_type
121         s_type = metainfo->type;
122
123         if (result == FALSE) {
124                 /* Fail */
125                 dbg("SEND FAIL");
126         }
127         else {
128                 dbg("SEND OK");
129         }
130 }
131 static gboolean on_sys_event_modem_power(CoreObject *o, const void *event_info, void *user_data)
132 {
133         struct tnoti_modem_power modem_power;
134         enum cp_state *state;
135
136         state = (enum cp_state*)event_info;
137         dbg("state : (0x%x)", *state);
138
139         if ( *state == CP_STATE_OFFLINE || *state == CP_STATE_CRASH_RESET ) {
140
141                 tcore_modem_set_powered(o, FALSE);
142
143                 if ( *state == CP_STATE_OFFLINE )
144                         modem_power.state = MODEM_STATE_OFFLINE;
145                 else
146                         modem_power.state = MODEM_STATE_ERROR;
147
148         } else {
149                 dbg("useless state : (0x%x)", *state);
150                 return TRUE;
151         }
152
153         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_POWER,
154                         sizeof(struct tnoti_modem_power), &modem_power);
155
156         return TRUE;
157 }
158 static gboolean on_event_modem_power(CoreObject *o, const void *event_info, void *user_data)
159 {
160         struct treq_modem_set_flightmode flight_mode_set;
161         struct tnoti_modem_power modem_power;
162         UserRequest *ur;
163         TcoreHal *h;
164         Storage *strg;
165
166         strg = tcore_server_find_storage(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), "vconf");
167         flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_SETAPPL_FLIGHT_MODE_BOOL);
168
169         h = tcore_object_get_hal(o);
170
171         tcore_hal_set_power_state(h, TRUE);
172
173         ur = tcore_user_request_new(NULL, NULL);
174         tcore_user_request_set_data(ur, sizeof(struct treq_modem_set_flightmode), &flight_mode_set);
175         tcore_user_request_set_command(ur, TREQ_MODEM_SET_FLIGHTMODE);
176         tcore_object_dispatch_request(o, ur);
177
178         ur = tcore_user_request_new(NULL, NULL);
179         tcore_user_request_set_command(ur, TREQ_MODEM_GET_IMEI);
180         tcore_object_dispatch_request(o, ur);
181
182         ur = tcore_user_request_new(NULL, NULL);
183         tcore_user_request_set_command(ur, TREQ_MODEM_GET_VERSION);
184         tcore_object_dispatch_request(o, ur);
185
186         tcore_modem_set_powered(o, TRUE);
187
188         modem_power.state = MODEM_STATE_ONLINE;
189
190         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_POWER,
191                         sizeof(struct tnoti_modem_power), &modem_power);
192
193         return TRUE;
194 }
195
196 static gboolean on_event_modem_phone_state(CoreObject *o, const void *event_info, void *user_data)
197 {
198         char* line = (char*)event_info;
199         GQueue *queue;
200         UserRequest *ur;
201         int err, status;
202         struct tresp_modem_set_flightmode res;
203         struct tnoti_modem_flight_mode modem_flight_mode;
204 #define SCFUN_MIN_FUNC 0
205 #define SCFUN_FULL_FUNC 1
206
207         dbg("received notification : %s", line);
208
209         at_tok_start(&line);
210
211         err = at_tok_nextint(&line, &status);
212
213         switch (status) {
214                 case SCFUN_MIN_FUNC:
215                         res.result = 0x01;
216                         tcore_modem_set_flight_mode_state(o, TRUE);
217                         break;
218
219                 case SCFUN_FULL_FUNC:
220                         res.result = 0x02;
221                         tcore_modem_set_flight_mode_state(o, FALSE);
222                         break;
223         }
224
225         queue = tcore_object_ref_user_data(o);
226         if (queue) {
227                 ur = util_pop_waiting_job(queue, ID_RESERVED_AT);
228                 if (ur) {
229                         tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE, sizeof(struct tresp_modem_set_flightmode), &res);
230                 }
231         }
232
233         modem_flight_mode.enable = tcore_modem_get_flight_mode_state(o);
234
235         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_FLIGHT_MODE,
236                         sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode);
237
238         return TRUE;
239 }
240 static void on_response_poweron(TcorePending *p, int data_len, const void *data, void *user_data)
241 {
242         char *line;
243         gboolean bpoweron = FALSE;
244         int response = 0;
245         int err;
246
247 #define CPAS_RES_READY          0
248 #define CPAS_RES_UNAVAIL        1
249 #define CPAS_RES_UNKNOWN        2
250 #define CPAS_RES_RINGING        3
251 #define CPAS_RES_CALL_PROGRESS  4
252 #define CPAS_RES_ASLEEP 5
253
254 //print sp_response - for debug
255         printResponse();
256
257         if(sp_response->success > 0){
258                 dbg("RESPONSE OK");
259                 //parse response
260                 line = sp_response->p_intermediates->line;
261
262                 err = at_tok_start(&line);
263                 if (err < 0) {
264                    bpoweron = FALSE;
265                    goto error;
266                 }
267
268                 err = at_tok_nextint(&line, &response);
269                 if (err < 0) {
270                         bpoweron =FALSE;
271                     goto error;
272                 }
273
274                 dbg("response %d",response);
275
276                 switch(response)
277                 {
278                         case CPAS_RES_READY:
279                         case CPAS_RES_RINGING:
280                         case CPAS_RES_CALL_PROGRESS:
281                         case CPAS_RES_ASLEEP:
282                                 bpoweron = TRUE;
283                         break;
284
285                         case CPAS_RES_UNAVAIL:
286                         case CPAS_RES_UNKNOWN:
287                         default:
288                                 bpoweron = FALSE;
289                         break;
290                 }
291         }else{
292                 dbg("RESPONSE NOK");
293                 bpoweron = FALSE;
294         }
295
296 error:
297 //5. release sp_response & s_responsePrefix - before sending user callback, because user callback can request additional request
298 // and if queue is empty, that req can be directly sent to mdm - can cause sp_response, s_responsePrefix dangling
299         ReleaseResponse();
300
301         if(bpoweron == TRUE){
302                 dbg("Power on NOTI received");
303                 //procees power up noti process
304                 on_event_modem_power(tcore_pending_ref_core_object(p), NULL, NULL);
305         }
306         else{ //poweron not complete - proceed same process again
307
308                 dbg("CPAS once again");
309                 s_modem_send_poweron(tcore_object_ref_plugin(tcore_pending_ref_core_object(p)));
310         }
311 }
312
313 static void on_response_set_flight_mode(TcorePending *p, int data_len, const void *data, void *user_data)
314 {
315         CoreObject *o = user_data;
316         UserRequest *ur;
317         char *line;
318         struct tresp_modem_set_flightmode res;
319         GQueue *queue;
320         int err;
321         int response;
322
323 //print sp_response - for debug
324         printResponse();
325         ur = tcore_pending_ref_user_request(p);
326
327         if(sp_response->success > 0)
328         {
329                 dbg("RESPONSE OK");
330                 //parse response
331                 queue = tcore_object_ref_user_data(o);
332                 if (queue)
333                 {
334                         ur = tcore_user_request_ref(ur);
335                         util_add_waiting_job(queue, ID_RESERVED_AT, ur);
336                 }
337
338                 ReleaseResponse();
339         }
340         else
341         {
342                 dbg("RESPONSE NOK");
343                 line = sp_response->finalResponse;
344                 err = at_tok_start(&line);
345                 if (err < 0)
346                 {
347                         dbg("err cause not specified or string corrupted");
348                         res.result = TCORE_RETURN_3GPP_ERROR;
349                 }
350                 else
351                 {
352                         err = at_tok_nextint(&line, &response);
353                         if (err < 0)
354                         {
355                                 dbg("err not specified or string not contail error");
356                                 res.result = TCORE_RETURN_3GPP_ERROR;
357                         }
358                         else
359                         {
360                                 res.result = convertCMEError((enum ATCMEError)response);
361                         }
362
363                         ReleaseResponse();
364
365                         tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE, sizeof(struct tresp_modem_set_flightmode), &res);
366                 }
367         }
368 }
369 static void on_response_imei(TcorePending *p, int data_len, const void *data, void *user_data)
370 {
371         TcorePlugin *plugin;
372         struct tresp_modem_get_imei res;
373         UserRequest *ur;
374         struct TelMiscSNInformation *imei_property;
375         char *line;
376         int response;
377         int err;
378
379         printResponse();
380
381         memset(&res, 0, sizeof(struct tresp_modem_get_imei));
382
383         if(sp_response->success > 0)
384         {
385                 dbg("RESPONSE OK");
386
387                 line = sp_response->p_intermediates->line;
388
389                 res.result = TCORE_RETURN_SUCCESS;
390                 strncpy(res.imei, line, 16);
391
392                 dbg("imei = [%s]", res.imei);
393
394                 plugin = tcore_pending_ref_plugin(p);
395                 imei_property = tcore_plugin_ref_property(plugin, "IMEI");
396                 if (imei_property)
397                 {
398                         imei_property->sn_index = TAPI_MISC_ME_IMEI;
399                         imei_property->sn_len = strlen(res.imei);
400                         memcpy(imei_property->szNumber, res.imei, imei_property->sn_len);
401                 }
402         }
403         else
404         {
405                 dbg("RESPONSE NOK");
406                 line = sp_response->finalResponse;
407
408                 err = at_tok_start(&line);
409                 if (err < 0)
410                 {
411                         dbg("err cause not specified or string corrupted");
412                            res.result = TCORE_RETURN_3GPP_ERROR;
413                 }
414                 else
415                 {
416                         err = at_tok_nextint(&line, &response);
417                         if (err < 0)
418                         {
419                                 dbg("err not specified or string not contail error");
420                                 res.result = TCORE_RETURN_3GPP_ERROR;
421                         }
422                         else
423                         {
424                                 res.result = convertCMEError((enum ATCMEError)response);
425                         }
426                 }
427         }
428
429         ReleaseResponse();
430
431         ur = tcore_pending_ref_user_request(p);
432         tcore_user_request_send_response(ur, TRESP_MODEM_GET_IMEI, sizeof(struct tresp_modem_get_imei), &res);
433
434 }
435
436 static void on_response_version(TcorePending *p, int data_len, const void *data, void *user_data)
437 {
438         TcorePlugin *plugin;
439         struct TelMiscVersionInformation *vi;
440         struct TelMiscVersionInformation *vi_property;
441         struct tresp_modem_get_version res;
442         UserRequest *ur;
443         char* line=NULL;
444         char *swver= NULL,*hwver=NULL, *caldate=NULL,*pcode=NULL,*id=NULL;
445
446         int response, err;
447
448         printResponse();
449
450 #define AT_VER_LEN 20
451         if(sp_response->success > 0)
452         {
453                 dbg("RESPONSE OK");
454
455                 line = sp_response->p_intermediates->line;
456                 err = at_tok_start(&line);
457
458                 err = at_tok_nextstr(&line,&swver);
459                 if(swver!=NULL)
460                         err = at_tok_nextstr(&line,&hwver);
461                 if(hwver!=NULL)
462                         err = at_tok_nextstr(&line,&caldate);
463                 if(caldate !=NULL)
464                         err = at_tok_nextstr(&line,&pcode);
465                 if(pcode !=NULL)
466                         err = at_tok_nextstr(&line,&id);
467
468                 dbg("version: sw=[%s], hw=[%s], rf_cal=[%s], product_code=[%s], model_id=[%s]", swver, hwver, caldate, pcode, id);
469
470                 vi = calloc(sizeof(struct TelMiscVersionInformation), 1);
471                 memcpy(vi->szSwVersion, swver, strlen(swver));
472                 memcpy(vi->szHwVersion, hwver, strlen(hwver));
473                 memcpy(vi->szRfCalDate, caldate, strlen(caldate));
474                 memcpy(vi->szProductCode, pcode,strlen(pcode));
475                 memcpy(vi->szModelId, id, strlen(id));
476
477                 memset(&res, 0, sizeof(struct tresp_modem_get_imei));
478                 snprintf(res.software, (AT_VER_LEN >strlen(swver) ?strlen(swver):AT_VER_LEN), "%s", swver);
479                 snprintf(res.hardware, (AT_VER_LEN >strlen(hwver) ?strlen(hwver):AT_VER_LEN), "%s", hwver);
480
481                 plugin = tcore_pending_ref_plugin(p);
482                 vi_property = tcore_plugin_ref_property(plugin, "VERSION");     
483                 memcpy(vi_property, vi, sizeof(struct TelMiscVersionInformation));
484         }
485         else
486         {
487                 dbg("RESPONSE NOK");
488                 line = sp_response->finalResponse;
489
490                 memset(&res, 0, sizeof(struct tresp_modem_get_version));
491
492                 err = at_tok_start(&line);
493                 if (err < 0)
494                 {
495                         dbg("err cause not specified or string corrupted");
496                            res.result = TCORE_RETURN_3GPP_ERROR;
497                 }
498                 else
499                 {
500                         err = at_tok_nextint(&line, &response);
501                         if (err < 0)
502                         {
503                                 dbg("err not specified or string not contail error");
504                                 res.result = TCORE_RETURN_3GPP_ERROR;
505                         }
506                         else
507                         {
508                                 res.result = convertCMEError((enum ATCMEError)response);
509                         }
510                 }
511         }
512
513         ReleaseResponse();
514
515         ur = tcore_pending_ref_user_request(p);
516         tcore_user_request_send_response(ur, TRESP_MODEM_GET_VERSION, sizeof(struct tresp_modem_get_version), &res);
517
518 }
519
520 static TReturn power_on(CoreObject *o, UserRequest *ur)
521 {
522
523         return TCORE_RETURN_SUCCESS;
524 }
525
526 static TReturn power_off(CoreObject *o, UserRequest *ur)
527 {
528         struct tnoti_modem_power modem_power;
529         modem_power.state = MODEM_STATE_OFFLINE;
530
531         tcore_modem_set_powered(o, FALSE);
532
533         tcore_server_send_notification( tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_POWER,
534                         sizeof(struct tnoti_modem_power), &modem_power);
535
536         return TCORE_RETURN_SUCCESS;
537 }
538 static TReturn power_reset(CoreObject *o, UserRequest *ur)
539 {
540
541         return TCORE_RETURN_SUCCESS;
542 }
543 static TReturn get_imei(CoreObject *o, UserRequest *ur)
544 {
545         TcorePlugin *p = NULL;
546         TcoreHal *h = NULL;
547         TcorePending *pending = NULL;
548         char* cmd_str = NULL;
549         struct ATReqMetaInfo metainfo;
550         int info_len =0;
551
552         p = tcore_object_ref_plugin(o);
553         h = tcore_object_get_hal(o);
554
555         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
556         metainfo.type = NUMERIC;
557         metainfo.responsePrefix[0] ='\0';
558         info_len = sizeof(struct ATReqMetaInfo);
559
560         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
561
562         cmd_str = g_strdup("AT+CGSN\r");
563         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",cmd_str, "N/A", strlen(cmd_str));
564
565         pending = tcore_pending_new(o, ID_RESERVED_AT);
566         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
567         free(cmd_str);
568         tcore_pending_set_timeout(pending, 0);
569         tcore_pending_set_response_callback(pending, on_response_imei, NULL);
570         tcore_pending_link_user_request(pending, ur);
571         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
572
573         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
574
575
576         tcore_hal_send_request(h, pending);
577
578         return TCORE_RETURN_SUCCESS;
579 }
580
581 static TReturn get_version(CoreObject *o, UserRequest *ur)
582 {
583         TcorePlugin *p = NULL;
584         TcoreHal *h = NULL;
585         TcorePending *pending = NULL;
586         char*                                           cmd_str = NULL;
587         struct ATReqMetaInfo metainfo;
588         int info_len =0;
589
590         p = tcore_object_ref_plugin(o);
591         h = tcore_object_get_hal(o);
592
593         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
594         metainfo.type = SINGLELINE;
595         memcpy(metainfo.responsePrefix,"+CGMR:",strlen("+CGMR:"));
596         info_len = sizeof(struct ATReqMetaInfo);
597
598         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
599
600         cmd_str = g_strdup("AT+CGMR\r");
601
602         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",cmd_str, "N/A", strlen(cmd_str));
603
604         pending = tcore_pending_new(o, ID_RESERVED_AT);
605         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
606         free(cmd_str);
607         tcore_pending_set_timeout(pending, 0);
608         tcore_pending_set_response_callback(pending, on_response_version, NULL);
609         tcore_pending_link_user_request(pending, ur);
610         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
611
612         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
613
614         tcore_hal_send_request(h, pending);
615
616         return TCORE_RETURN_SUCCESS;
617 }
618
619 static TReturn set_flight_mode(CoreObject *o, UserRequest *ur)
620 {
621         TcorePlugin *p = NULL;
622         TcoreHal *h = NULL;
623         TcorePending *pending = NULL;
624         const struct treq_modem_set_flightmode *req_data;
625         char*                                           cmd_str = NULL;
626         struct ATReqMetaInfo metainfo;
627         int info_len =0;
628
629         p = tcore_object_ref_plugin(o);
630         h = tcore_object_get_hal(o);
631
632         req_data = tcore_user_request_ref_data(ur, NULL);
633
634         if (req_data->enable) {
635                 dbg("Flight mode on/n");
636                 cmd_str = g_strdup("AT+CFUN=0\r");
637         }
638         else {
639                 dbg("Flight mode off/n");
640                 cmd_str = g_strdup("AT+CFUN=1\r");
641         }
642
643         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
644         metainfo.type = NO_RESULT;
645         metainfo.responsePrefix[0] ='\0';
646         info_len = sizeof(struct ATReqMetaInfo);
647
648         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
649
650         dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",cmd_str, "N/A", strlen(cmd_str));
651
652         pending = tcore_pending_new(o, ID_RESERVED_AT);
653         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
654         free(cmd_str);
655         tcore_pending_set_timeout(pending, 0);
656         tcore_pending_set_response_callback(pending, on_response_set_flight_mode, o);
657         tcore_pending_link_user_request(pending, ur);
658         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
659
660         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
661
662         tcore_hal_send_request(h, pending);
663
664         return TCORE_RETURN_SUCCESS;
665 }
666
667 static struct tcore_modem_operations modem_ops =
668 {
669         .power_on = power_on,
670         .power_off = power_off,
671         .power_reset = power_reset,
672         .set_flight_mode = set_flight_mode,
673         .get_imei = get_imei,
674         .get_version = get_version,
675 };
676
677 gboolean s_modem_init(TcorePlugin *p, TcoreHal *h)
678 {
679         CoreObject *o;
680         GQueue *work_queue;
681         struct TelMiscVersionInformation *vi_property;
682         struct TelMiscSNInformation *imei_property;
683
684         o = tcore_modem_new(p, "modem", &modem_ops, h);
685         if (!o)
686                 return FALSE;
687
688         work_queue = g_queue_new();
689         tcore_object_link_user_data(o, work_queue);
690
691         tcore_object_add_callback(o, EVENT_SYS_NOTI_MODEM_POWER, on_sys_event_modem_power, NULL);
692
693         tcore_object_add_callback(o, EVENT_MODEM_POWER, on_event_modem_power, NULL);
694         tcore_object_add_callback(o, EVENT_MODEM_PHONE_STATE, on_event_modem_phone_state, NULL);
695
696         vi_property = calloc(sizeof(struct TelMiscVersionInformation), 1);
697         tcore_plugin_link_property(p, "VERSION", vi_property);
698
699         imei_property = calloc(sizeof(struct TelMiscSNInformation), 1);
700         tcore_plugin_link_property(p, "IMEI", imei_property);
701
702         return TRUE;
703 }
704
705 void s_modem_exit(TcorePlugin *p)
706 {
707         CoreObject *o;
708         GQueue *work_queue;
709         struct TelMiscVersionInformation *vi_property;
710         struct TelMiscSNInformation *imei_property;
711
712         if (!p)
713                 return;
714
715         o = tcore_plugin_ref_core_object(p, "modem");
716
717         work_queue = tcore_object_ref_user_data(o);
718         g_queue_free(work_queue);
719
720         vi_property = tcore_plugin_ref_property(p, "VERSION");
721         if (vi_property)
722                 free(vi_property);
723
724         imei_property = tcore_plugin_ref_property(p, "IMEI");
725         if (imei_property)
726                 free(imei_property);
727
728         tcore_modem_free(o);
729 }
730
731 gboolean s_modem_send_poweron(TcorePlugin *p)
732 {
733         UserRequest* ur;
734         TcoreHal* hal;
735         TcorePending *pending = NULL;
736         CoreObject *o;
737
738         char*                                           cmd_str = NULL;
739         struct ATReqMetaInfo metainfo;
740         int info_len =0;
741
742         ur = tcore_user_request_new(NULL, NULL);
743
744         memset(&metainfo, 0, sizeof(struct ATReqMetaInfo));
745         metainfo.type = SINGLELINE;
746         memcpy(metainfo.responsePrefix,"+CPAS:",strlen("+CPAS:"));
747         info_len = sizeof(struct ATReqMetaInfo);
748         tcore_user_request_set_metainfo(ur, info_len, &metainfo);
749
750         cmd_str = g_strdup("AT+CPAS\r");
751
752         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d",cmd_str, metainfo.responsePrefix, strlen(cmd_str));
753
754         o = tcore_plugin_ref_core_object(p, "modem");
755         hal = tcore_object_get_hal(o);
756
757         pending = tcore_pending_new(o, ID_RESERVED_AT);
758         tcore_pending_set_request_data(pending, strlen(cmd_str), cmd_str);
759         free(cmd_str);
760         tcore_pending_set_timeout(pending, 0);
761         tcore_pending_set_response_callback(pending, on_response_poweron, NULL);
762         tcore_pending_link_user_request(pending, ur);
763         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
764
765         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
766
767         tcore_hal_send_request(hal, pending);
768
769         return TRUE;
770
771 }