Tizen 2.0 beta Release
[profile/ivi/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: 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
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include <glib.h>
28
29 #include <tcore.h>
30 #include <hal.h>
31 #include <core_object.h>
32 #include <plugin.h>
33 #include <queue.h>
34 #include <co_modem.h>
35 #include <storage.h>
36 #include <server.h>
37 #include <at.h>
38
39 #include "s_common.h"
40 #include "s_modem.h"
41
42 #define ID_RESERVED_AT 0x0229
43
44 #define MAX_VERSION_LEN 32
45 #define TAPI_MISC_ME_SN_LEN_MAX                         32
46 #define TAPI_MISC_PRODUCT_CODE_LEN_MAX          32
47 #define TAPI_MISC_MODEL_ID_LEN_MAX                      17
48 #define TAPI_MISC_PRL_ERI_VER_LEN_MAX           17
49
50 #define CPAS_RES_READY          0
51 #define CPAS_RES_UNAVAIL                1
52 #define CPAS_RES_UNKNOWN                2
53 #define CPAS_RES_RINGING                3
54 #define CPAS_RES_CALL_PROGRESS  4
55 #define CPAS_RES_ASLEEP           5
56 #define AT_VER_LEN 20
57
58
59 enum cp_state {
60         CP_STATE_OFFLINE,
61         CP_STATE_CRASH_RESET,
62         CP_STATE_CRASH_EXIT,
63         CP_STATE_BOOTING,
64         CP_STATE_ONLINE,
65         CP_STATE_NV_REBUILDING,
66         CP_STATE_LOADER_DONE,
67 };
68
69 typedef enum {
70         TAPI_MISC_ME_IMEI = 0x00, /**< 0x00: IMEI, GSM/UMTS device */
71         TAPI_MISC_ME_ESN = 0x01, /**< 0x01: ESN(Electronic Serial Number), It`s essentially run out. CDMA device */
72         TAPI_MISC_ME_MEID = 0x02, /**< 0x02: MEID, This value can have hexa decimal digits. CDMA device */
73         TAPI_MISC_ME_MAX = 0xff /**< 0xff: reserved */
74 } TelMiscSNIndexType_t;
75
76 typedef struct {
77         TelMiscSNIndexType_t sn_index; /**< serial number index */
78         int sn_len; /**< Length */
79         unsigned char szNumber[TAPI_MISC_ME_SN_LEN_MAX]; /**< Number */
80 } TelMiscSNInformation;
81
82 /**
83  * Mobile Equipment Version Information
84  */
85 typedef struct {
86         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 */
87         unsigned char szSwVersion[MAX_VERSION_LEN]; /**< Software version, null termination */
88         unsigned char szHwVersion[MAX_VERSION_LEN]; /**< Hardware version, null termination */
89         unsigned char szRfCalDate[MAX_VERSION_LEN]; /**< Calculation Date, null termination */
90         unsigned char szProductCode[TAPI_MISC_PRODUCT_CODE_LEN_MAX]; /**< product code, null termination */
91         unsigned char szModelId[TAPI_MISC_MODEL_ID_LEN_MAX]; /**< model id (only for CDMA), null termination */
92         unsigned char prl_nam_num; /**< number of PRL NAM fields */
93         unsigned char szPrlVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3];/**< prl version (only for CDMA), null termination */
94         unsigned char eri_nam_num; /**< number of PRL NAM fields */
95         unsigned char szEriVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3];/**< eri version (only for CDMA), null termination */
96 } TelMiscVersionInformation;
97
98 void prepare_and_send_pending_request(TcorePlugin *plugin, char *co_name, const char *at_cmd, const char* prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback);
99 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data); // from Kernel
100 void on_response_bootup_subscription(TcorePending *p, gboolean result, void *user_data);
101 void on_response_last_bootup_subscription(TcorePending *p, gboolean result, void *user_data);
102 static void on_timeout_modem_poweron(TcorePending *p, void *user_data);
103
104 static void on_timeout_modem_poweron(TcorePending *p, void *user_data)
105 {
106         unsigned int data_len = 0;
107         char data[] = "AT+CPAS\r";                      
108         dbg("TIMEOUT for 1st AT Command !!!!! NO Response for initial AT command. Resending it");       
109         data_len = sizeof(data);
110         
111         /* Retransmit 1st AT command directly via HAL, don't disturb pending queue. */
112         /* HAL was passed as user_data, re-use it */
113         if (user_data) 
114         {
115                 tcore_hal_send_data(user_data, data_len, (void *)data); 
116         }
117 }
118
119 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data)
120 {
121         dbg("on_confirmation_modem_message_send - msg out from queue.\n");
122
123         if (result == FALSE) {
124                 /* Fail */
125                 dbg("SEND FAIL");
126         }
127         else {
128                 dbg("SEND OK");
129         }
130 }
131
132 void prepare_and_send_pending_request(TcorePlugin *plugin, char *co_name, const char *at_cmd, const char* prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback)
133 {
134         TcoreATRequest *req = NULL;
135         TcoreHal *hal;
136         CoreObject *o= NULL;
137         TcorePending *pending = NULL;
138         TReturn ret;
139         
140         o = tcore_plugin_ref_core_object(plugin, co_name);
141         hal = tcore_object_get_hal(o);
142         
143         pending = tcore_pending_new(o, 0);
144         if(!pending)
145                 dbg("Pending is NULL");
146         req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
147
148         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
149
150         tcore_pending_set_request_data(pending, 0, req);
151         tcore_pending_set_response_callback(pending, callback, NULL);
152         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
153         tcore_pending_link_user_request(pending, NULL); //set user request to NULL - this is intenal request
154         ret = tcore_hal_send_request(hal, pending);
155         return;
156 }
157
158 void on_response_bootup_subscription(TcorePending *p, gboolean result, void *user_data)
159 {       
160         dbg("enry of on_response_bootup_subscription() - response comes\n");
161
162         if (result == FALSE) {
163                 /* Fail */
164                 dbg("result ERROR");
165         }
166         else {
167                 dbg("result OK");
168         }
169 }
170
171 void on_response_last_bootup_subscription(TcorePending *p, gboolean result, void *user_data)
172 {
173         dbg("enry of on_response_last_bootup_subscription() - final response comes\n");
174
175         if (result == FALSE) {
176                 /* Fail */
177                 dbg("SEND FAIL");
178         }
179         else {
180                 dbg("SEND OK");
181         }
182         
183         dbg("Response for AT+CLIP. Boot-up configration completed for IMC modem. Bring CP to online based on Flightmode status\n");
184         on_event_modem_power(NULL, NULL, tcore_pending_ref_plugin(p));
185 }
186
187
188
189 static void on_response_power_off(TcorePending *p, int data_len, const void *data, void *user_data)
190 {
191         CoreObject *o = 0;
192         TcoreHal *h = 0;
193         o = tcore_pending_ref_core_object(p);
194         h = tcore_object_get_hal(o);
195
196         dbg("modem power off");
197
198         tcore_hal_set_power_state(h, FALSE);
199 }
200
201 static void on_response_set_flight_mode(TcorePending *p, int data_len, const void *data, void *user_data)
202 {
203         CoreObject *o = user_data;
204         UserRequest *ur = NULL;
205         const TcoreATResponse *resp = data;
206         GSList *tokens=NULL;
207         const char *line;
208         struct tresp_modem_set_flightmode res;
209         GQueue *queue;
210         int err;
211         int response;
212         struct tnoti_modem_flight_mode modem_flight_mode;
213
214         o = tcore_pending_ref_core_object(p);
215
216         
217         if(resp->success > 0){
218                 dbg("RESPONSE OK - flight mode operation finished");
219                 res.result = TCORE_RETURN_SUCCESS;
220         }
221         else    {
222                 dbg("RESPONSE NOK");
223                 line = (const char*)resp->final_response;
224                 tokens = tcore_at_tok_new(line);
225
226                 if (g_slist_length(tokens) < 1) {
227                         dbg("err cause not specified or string corrupted");
228                         res.result = TCORE_RETURN_3GPP_ERROR;
229                 }
230                 else    {
231                         response = atoi(g_slist_nth_data(tokens, 0));
232                         /* TODO: CMEE error mapping is required. */
233                         res.result = TCORE_RETURN_3GPP_ERROR;
234                 }
235         }
236
237         ur = tcore_pending_ref_user_request(p);
238         if(NULL == ur){
239                 dbg("No user request ");
240         }
241         else    {
242                 tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE, sizeof(struct tresp_modem_set_flightmode), &res);
243         }
244
245         if(resp->success > 0){  
246                 modem_flight_mode.enable = tcore_modem_get_flight_mode_state(o);
247                 
248                 dbg("sucess case - Sending Flight Mode Notification (%d) to Server",modem_flight_mode.enable);
249                 
250                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_FLIGHT_MODE,
251                                 sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode);
252         }
253         
254         tcore_at_tok_free(tokens);
255 }
256
257 static void on_response_imei(TcorePending *p, int data_len, const void *data, void *user_data)
258 {
259         const TcoreATResponse* resp = data;
260         TcorePlugin *plugin;
261         struct tresp_modem_get_imei res;
262         TelMiscSNInformation *imei_property;
263         UserRequest* ur = NULL;
264         GSList *tokens=NULL;
265         const char *line;
266         int response;
267         int err;
268
269         memset(&res, 0, sizeof(struct tresp_modem_get_imei));
270
271         if(resp->success > 0)
272         {
273                 dbg("RESPONSE OK");
274                 if(resp->lines) {
275                         line = (const char*)resp->lines->data;
276                         tokens = tcore_at_tok_new(line);
277                         if (g_slist_length(tokens) != 1) {
278                                 msg("invalid message");
279                                 goto OUT;
280                         }
281                 }
282                 res.result = TCORE_RETURN_SUCCESS;
283                 strncpy(res.imei, g_slist_nth_data(tokens, 0), 16);
284
285                 dbg("imei = [%s]", res.imei);
286
287                 plugin = tcore_pending_ref_plugin(p);
288                 imei_property = tcore_plugin_ref_property(plugin, "IMEI");
289                 if (imei_property)
290                 {
291                         imei_property->sn_index = TAPI_MISC_ME_IMEI;
292                         imei_property->sn_len = strlen(res.imei);
293                         memcpy(imei_property->szNumber, res.imei, imei_property->sn_len);
294                 }
295         }
296         else
297         {
298                 dbg("RESPONSE NOK");
299                 if(resp->lines) {
300                         line = (const char*)resp->lines->data;
301                         tokens = tcore_at_tok_new(line);
302                 }
303
304                 memset(&res, 0, sizeof(struct tresp_modem_get_version));
305
306
307                 if (g_slist_length(tokens) < 1) {
308                         dbg("err cause not specified or string corrupted");
309                     res.result = TCORE_RETURN_3GPP_ERROR;
310                 }
311                 else
312                 {
313                         response = atoi(g_slist_nth_data(tokens, 0));
314                         /* TODO: CMEE error mapping is required. */
315                 res.result = TCORE_RETURN_3GPP_ERROR;
316                 }
317         }
318
319         ur = tcore_pending_ref_user_request(p); 
320         tcore_user_request_send_response(ur, TRESP_MODEM_GET_IMEI, sizeof(struct tresp_modem_get_imei), &res);  
321
322 OUT:
323         tcore_at_tok_free(tokens);
324
325 }
326
327 static void on_response_version(TcorePending *p, int data_len, const void *data, void *user_data)
328 {
329         const TcoreATResponse *resp = data;
330         TcorePlugin *plugin;
331         TelMiscVersionInformation *vi;
332         TelMiscVersionInformation *vi_property;
333         struct tresp_modem_get_version res;
334         UserRequest *ur;
335         GSList* tokens = NULL;
336         const char* line=NULL;
337         char *swver= NULL,*hwver=NULL, *caldate=NULL,*pcode=NULL,*id=NULL;
338
339         int response, err;
340
341         if(resp->success > 0)
342         {
343                 dbg("RESPONSE OK");
344                 if(resp->lines) {
345                         line = (const char*)resp->lines->data;
346                         tokens = tcore_at_tok_new(line);
347                         if (g_slist_length(tokens) != 5) {
348                                 msg("invalid message");
349                                 goto OUT;
350                         }
351                 }
352
353                 swver = g_slist_nth_data(tokens, 0);
354                 hwver = g_slist_nth_data(tokens, 1);
355                 caldate = g_slist_nth_data(tokens, 2);
356                 pcode = g_slist_nth_data(tokens, 3);
357                 id = g_slist_nth_data(tokens, 4);
358
359                 dbg("version: sw=[%s], hw=[%s], rf_cal=[%s], product_code=[%s], model_id=[%s]", swver, hwver, caldate, pcode, id);
360
361                 vi = calloc(sizeof(TelMiscVersionInformation), 1);
362                 if(NULL!=swver)
363                         memcpy(vi->szSwVersion, swver, strlen(swver));
364                 if(NULL!=hwver)
365                         memcpy(vi->szHwVersion, hwver, strlen(hwver));
366                 if(NULL!=caldate)
367                         memcpy(vi->szRfCalDate, caldate, strlen(caldate));
368                 if(NULL!=pcode)
369                         memcpy(vi->szProductCode, pcode,strlen(pcode));
370                 if(NULL!=id)
371                         memcpy(vi->szModelId, id, strlen(id));
372
373                 memset(&res, 0, sizeof(struct tresp_modem_get_version));
374
375                 if(NULL!=swver)         
376                         snprintf(res.software, (AT_VER_LEN >strlen(swver) ?strlen(swver):AT_VER_LEN), "%s", swver);
377                 if(NULL!=hwver)
378                         snprintf(res.hardware, (AT_VER_LEN >strlen(hwver) ?strlen(hwver):AT_VER_LEN), "%s", hwver);
379
380                 plugin = tcore_pending_ref_plugin(p);
381                 vi_property = tcore_plugin_ref_property(plugin, "VERSION");
382                 memcpy(vi_property, vi, sizeof(TelMiscVersionInformation));
383         }
384         else
385         {
386                 dbg("RESPONSE NOK");
387                 if(resp->lines) {
388                         line = (const char*)resp->lines->data;
389                         tokens = tcore_at_tok_new(line);
390                 }
391
392                 memset(&res, 0, sizeof(struct tresp_modem_get_version));
393
394
395                 if (g_slist_length(tokens) < 1) {
396                         dbg("err cause not specified or string corrupted");
397                     res.result = TCORE_RETURN_3GPP_ERROR;
398                 }
399                 else
400                 {
401                         response = atoi(g_slist_nth_data(tokens, 0));
402                         /* TODO: CMEE error mapping is required. */
403                 res.result = TCORE_RETURN_3GPP_ERROR;
404                 }
405         }
406
407         ur = tcore_pending_ref_user_request(p);
408         tcore_user_request_send_response(ur, TRESP_MODEM_GET_VERSION, sizeof(struct tresp_modem_get_version), &res);
409
410 OUT:
411         tcore_at_tok_free(tokens);
412
413 }
414
415 static gboolean on_event_bootup_sim_status(CoreObject *o, const void *event_info, void *user_data)
416 {
417         GSList *tok = NULL;
418         GSList *lines = NULL;
419         int value = -1;
420         char* line = NULL;
421
422         lines = (GSList*)event_info;
423         if (1 != g_slist_length(lines)) {
424                 dbg("unsolicited msg but multiple line");
425             goto OUT;
426         }
427         line  = (char*)(lines->data);
428         dbg("on_bootup_event_sim_status notification : %s", line);
429
430         tok = tcore_at_tok_new(line);
431         value = atoi(g_slist_nth_data(tok, 0));
432
433         if(7 == value){
434                 dbg("SIM ready. request COPS & remove callback");
435                 prepare_and_send_pending_request(tcore_object_ref_plugin(o), "umts_network", "AT+COPS=0", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
436                 return FALSE;
437         }
438
439 OUT:
440         return TRUE;
441 }
442
443
444
445 gboolean on_event_modem_power(TcoreAT *at, const char *line, TcorePlugin *p)
446 {
447         CoreObject *o;
448         struct treq_modem_set_flightmode flight_mode_set;
449         struct tnoti_modem_power modem_power;
450         TcoreHal *h;
451         Storage *strg;
452         
453         o = tcore_plugin_ref_core_object(p, "modem");
454         
455         strg = tcore_server_find_storage(tcore_plugin_ref_server(p), "vconf");
456         flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_SETAPPL_FLIGHT_MODE_BOOL);
457
458         tcore_hal_set_power_state(h, TRUE);
459         
460         /* Set Flight mode as per AP settings */
461         if (flight_mode_set.enable)
462         { /* Radio Off */
463                 prepare_and_send_pending_request(p, "modem", "AT+CFUN=4", NULL, TCORE_AT_NO_RESULT, on_response_set_flight_mode);
464                 tcore_modem_set_flight_mode_state(o, TRUE);
465         }
466         else
467         {/* Radio On */
468                 prepare_and_send_pending_request(p, "modem", "AT+CFUN=1", NULL, TCORE_AT_NO_RESULT, on_response_set_flight_mode);
469                 tcore_modem_set_flight_mode_state(o, FALSE);
470         }
471                 
472         /* Get IMEI */
473         prepare_and_send_pending_request(p, "modem", "AT+CGSN", NULL, TCORE_AT_NUMERIC, on_response_imei);
474
475         /* Get Version Number  */
476         prepare_and_send_pending_request(p, "modem", "AT+CGMR", NULL, TCORE_AT_SINGLELINE, on_response_version);
477         
478         tcore_modem_set_powered(o, TRUE);
479
480         modem_power.state = MODEM_STATE_ONLINE;
481
482         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_POWER,
483                         sizeof(struct tnoti_modem_power), &modem_power);
484
485         return TRUE;
486 }
487
488
489 #ifdef ENABLE_CMUX
490
491 static void on_response_setupmux(TcorePending *p, int data_len, const void *data, void *user_data)
492 {
493         TcorePlugin *plugin = NULL;
494         
495         plugin = tcore_pending_ref_plugin(p);
496         
497         /* TODO: Initialize MUX module.
498          *       Append each MUX HAL to each Co-Object while initialization.
499          * API: tcore_object_set_hal(CoreObject *o, TcoreHal *h)
500          *
501          * After MUX setup, AT parse functionality of PHY HAL
502          * should be disabled.
503          * e.g.) plugin = tcore_pending_ref_plugin((TcorePending*) p);
504          *       hal    = tcore_plugin_ref_hal((TcorePlugin*) plugin);
505          *       tcore_hal_disable_queue((TcoreHal*) hal);
506          */
507
508         /* TODO: Should be moved to ...
509          * Proceed power up noti process after MUX initialization.
510          */
511         s_modem_send_poweron(NULL, NULL, plugin);
512 }
513
514
515
516 static void setup_mux(CoreObject *o)
517 {
518         TcoreHal* hal;
519         TcoreATRequest *req;
520         TcorePending *pending = NULL;
521
522
523         prepare_and_send_pending_request(p, "modem", "AT+CMUX=0,0,,1509,10,3,30,,", +CMUX, TCORE_AT_NO_RESULT, on_response_set_flight_mode);
524
525         /* HAL has type itself,
526          * e.g.) TCORE_HAL_MODE_AT
527          */
528         hal = tcore_object_get_hal(o);
529         pending = tcore_pending_new(o, 0);
530
531         /* Set Metainfo into TcorePending directly
532          * using TcoreATRequest
533          * command type: e.g.) SINGLELINE
534          * response prefix
535          */
536         req = tcore_at_request_new("AT+CMUX=0,0,,1509,10,3,30,,", "+CMUX", TCORE_AT_NO_RESULT);
537
538         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
539
540         tcore_pending_set_request_data(pending, 0, req);
541         tcore_pending_set_response_callback(pending, on_response_setupmux, hal);
542         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
543
544         tcore_hal_send_request(hal, pending);
545 }
546
547 #endif
548         
549 static void on_response_enable_logging(TcorePending *p, int data_len, const void *data, void *user_data)
550 {
551         const TcoreATResponse *resp = data;
552         TcorePlugin *plugin = NULL;
553         
554         plugin = tcore_pending_ref_plugin(p);
555         
556         /* DELETE ME: only for DEBUG */
557         if (!resp)
558                 dbg("no data");
559
560         dbg("response...(result = %d, final_response = '%s')", resp->success, resp->final_response);
561
562         if(resp->success){
563                 dbg("RESPONSE OK");
564                 dbg("Enabling CP logging is success !!!\n");
565
566         }else {
567                 dbg("RESPONSE NOK");
568                 dbg("Enabling CP logging is failed !!!\n");
569         }
570
571
572 #ifdef ENABLE_CMUX
573         dbg("call setup_mux");
574         prepare_and_send_pending_request(plugin, "modem", "AT+CMUX=0,0,,1509,10,3,30,,", +CMUX, TCORE_AT_NO_RESULT, on_response_setupmux);
575         /*setup_mux(tcore_pending_ref_core_object(p));*/
576 #else
577
578         /* XCALLSTAT subscription */
579         prepare_and_send_pending_request(plugin, "call", "at+xcallstat=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
580
581         /* XSIMSTATE subscription */
582         prepare_and_send_pending_request(plugin, "sim", "at+xsimstate=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
583         
584         /* CREG subscription */
585         prepare_and_send_pending_request(plugin, "umts_network", "at+creg=2", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
586
587         /* CGREG subscription */
588         prepare_and_send_pending_request(plugin, "umts_network", "at+cgreg=2", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
589
590         /* XMER subscription */
591         prepare_and_send_pending_request(plugin, "umts_network", "at+xmer=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
592
593         /* CGEREP subscription */
594         prepare_and_send_pending_request(plugin, "umts_ps", "at+cgerep=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
595
596         /* XDATASTAT subscription */
597         prepare_and_send_pending_request(plugin, "umts_ps", "at+xdatastat=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
598
599         /* CMGF subscription */
600         prepare_and_send_pending_request(plugin, "umts_sms", "at+cmgf=0", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
601
602         /* CSSN subscription */
603         prepare_and_send_pending_request(plugin, "call", "at+cssn=1,1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
604
605         /* CUSD subscription */
606         prepare_and_send_pending_request(plugin, "call", "at+cusd=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
607
608         /* XDNS subscription */
609         prepare_and_send_pending_request(plugin, "umts_ps", "at+xdns=1,1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
610
611         /* CLIP subscription */
612         prepare_and_send_pending_request(plugin, "call", "at+clip=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
613
614         /*CMEE subscription*/
615         prepare_and_send_pending_request(plugin,"umts_ps","at+cmee=2",NULL,TCORE_AT_NO_RESULT, on_response_bootup_subscription);
616
617
618         /*incoming sms and cb subscription*/
619         prepare_and_send_pending_request(plugin,"umts_sms","at+cnmi=1,2,2,2,0",NULL,TCORE_AT_NO_RESULT, on_response_bootup_subscription);
620
621         /*message service subscription*/
622         prepare_and_send_pending_request(plugin,"umts_sms","at+csms=1",NULL,TCORE_AT_NO_RESULT, on_response_bootup_subscription);
623
624         /* text/pdu mode subscription*/
625         prepare_and_send_pending_request(plugin,"umts_sms","at+cmgf=0",NULL,TCORE_AT_NO_RESULT, on_response_last_bootup_subscription);
626 #if 0
627         /* Check for SIM PIN status */
628         prepare_and_send_pending_request(plugin, "sim", "at+cpin?", on_response_bootup_subscription);
629 #endif
630         
631 #endif
632 }
633
634 static void _send_enable_logging_command(CoreObject *o)
635 {
636         TcoreATRequest *req;
637         TcoreHal *hal;
638         TcorePending *pending;
639         TReturn ret;
640         /* DLELTE ME */
641         dbg("Send Trace enabling command for CP logging. \n");
642
643         if(!o){
644                 dbg("Co-object is Null !!\n");
645                 //goto error;
646         }
647
648         hal = tcore_object_get_hal(o);
649         pending = tcore_pending_new(o, 0);
650         req = tcore_at_request_new("at+xsystrace=1,\"digrf=1;bb_sw=1;3g_sw=1\",\"digrf=0x84\",\"oct=4\";+xsystrace=11;+trace=1", NULL, TCORE_AT_NO_RESULT);
651
652         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
653
654         tcore_pending_set_request_data(pending, 0, req);
655         tcore_pending_set_response_callback(pending, on_response_enable_logging, hal);
656         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
657
658         ret = tcore_hal_send_request(hal, pending);
659         if(ret != TCORE_RETURN_SUCCESS)
660                 dbg("tcore_hal_send_request fail !!! (hal: 0x%x, pending: 0x%x)\n", hal, pending);
661
662 }
663
664 static void on_response_poweron(TcorePending *p, int data_len, const void *data, void *user_data)
665 {
666         const TcoreATResponse *resp = data;
667         GSList*tokens=NULL;
668         const char *line=NULL;
669         gboolean bpoweron = FALSE;
670         int response = 0;
671         int err;
672         
673         if(resp->success){
674                 dbg("RESPONSE OK");
675                 /* Parse AT Response */
676                 if (resp->lines) {
677                         line = (const char *)resp->lines->data;
678                         tokens = tcore_at_tok_new(line);
679                         if (g_slist_length(tokens) != 1) {
680                                 dbg("invalid message");
681                                 bpoweron = FALSE;
682                                 goto error;
683                         }
684                 }
685
686                 response = atoi(g_slist_nth_data(tokens, 0));
687
688                 dbg("CPAS: response %d",response);
689
690                 switch(response)
691                 {
692                         case CPAS_RES_READY:
693                         case CPAS_RES_RINGING:
694                         case CPAS_RES_CALL_PROGRESS:
695                         case CPAS_RES_ASLEEP:
696                                 bpoweron = TRUE;
697                         break;
698
699                         case CPAS_RES_UNAVAIL:
700                         case CPAS_RES_UNKNOWN:
701                         default:
702                                 dbg("unvail/unknown,but response received - CP can communicate - proceed bootup");
703                                 //bpoweron = FALSE;
704                                 bpoweron = TRUE;
705                         break;
706                 }
707         }else{
708                 dbg("CPAS: RESPONSE NOK");
709                 bpoweron = FALSE;
710         }
711
712 error:
713         /* DELE ME: AT request & response are freed after AT processing in HAL.
714          * ref.) _emit_pending_response (libtcore/src/at.c)
715          */
716          tcore_at_tok_free(tokens);
717
718         if(bpoweron == TRUE){
719                 dbg("Power on NOTI received, (pending: 0x%x, co: 0x%x)\n", p, tcore_pending_ref_core_object(p));
720
721                 _send_enable_logging_command(tcore_pending_ref_core_object(p));
722         }
723         else{
724                 dbg("CP is not ready, send CPAS once again");
725                 s_modem_send_poweron(tcore_object_ref_plugin(tcore_pending_ref_core_object(p)));
726         }
727 }
728
729 static TReturn power_on(CoreObject *o, UserRequest *ur)
730 {
731
732         return TCORE_RETURN_SUCCESS;
733 }
734
735 static TReturn power_off(CoreObject *o, UserRequest *ur)
736 {
737         TcoreHal* hal;
738         TcoreATRequest *req;
739         TcorePending *pending = NULL;
740
741         /* FIXME: Before MUX setup, use PHY HAL directly. */
742         hal = tcore_object_get_hal(o);
743
744         pending = tcore_pending_new(o, 0);
745
746         /* TODO:
747          * Need to mapping or define AT command
748          * including prefix if neccessary otherwise NULL.
749          * Response type (e.g. TCORE_AT_SINGLELINE)
750          */
751         req = tcore_at_request_new("AT+CFUN=0", NULL, TCORE_AT_NO_RESULT);
752
753         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
754
755         tcore_pending_set_request_data(pending, 0, req);
756         tcore_pending_set_response_callback(pending, on_response_power_off, hal);
757         tcore_pending_link_user_request(pending, ur);
758         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
759
760         tcore_hal_send_request(hal, pending);
761
762         return TCORE_RETURN_SUCCESS;
763 }
764
765 static TReturn power_reset(CoreObject *o, UserRequest *ur)
766 {
767
768         return TCORE_RETURN_SUCCESS;
769 }
770
771 static TReturn get_imei(CoreObject *o, UserRequest *ur)
772 {
773         TcoreHal* hal;
774         TcoreATRequest *req;
775         TcorePending *pending = NULL;
776
777         hal = tcore_object_get_hal(o);
778         pending = tcore_pending_new(o, 0);
779
780         req = tcore_at_request_new("AT+CGSN", NULL, TCORE_AT_NUMERIC);
781
782         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
783
784         tcore_pending_set_request_data(pending, 0, req);
785         tcore_pending_set_response_callback(pending, on_response_imei, hal);
786         tcore_pending_link_user_request(pending, ur);
787         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
788
789         tcore_hal_send_request(hal, pending);
790
791         return TCORE_RETURN_SUCCESS;
792 }
793
794
795 static TReturn get_version(CoreObject *o, UserRequest *ur)
796 {
797         TcoreHal* hal;
798         TcoreATRequest *req;
799         TcorePending *pending = NULL;
800
801         hal = tcore_object_get_hal(o);
802         pending = tcore_pending_new(o, 0);
803
804         req = tcore_at_request_new("AT+CGMR", NULL, TCORE_AT_SINGLELINE);
805
806         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
807
808         tcore_pending_set_request_data(pending, 0, req);
809         tcore_pending_set_response_callback(pending, on_response_version, hal);
810         tcore_pending_link_user_request(pending, ur);
811         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
812
813         tcore_hal_send_request(hal, pending);
814
815         return TCORE_RETURN_SUCCESS;
816 }
817
818 static TReturn set_flight_mode(CoreObject *o, UserRequest *ur)
819 {
820         TcoreHal* hal;
821         TcoreATRequest *req;
822         TcorePending *pending = NULL;
823         const struct treq_modem_set_flightmode *req_data;
824         char* cmd_str = NULL;
825
826         hal = tcore_object_get_hal(o);
827         pending = tcore_pending_new(o, 0);
828
829         req_data = tcore_user_request_ref_data(ur, NULL);
830
831         if (req_data->enable) {
832                 dbg("Flight mode on/n");
833                 cmd_str = g_strdup("AT+CFUN=4\r");
834         }
835         else {
836                 dbg("Flight mode off/n");
837                 cmd_str = g_strdup("AT+CFUN=1\r");
838         }
839
840         req = tcore_at_request_new((const char*)cmd_str, NULL, TCORE_AT_NO_RESULT);
841
842         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
843
844         tcore_pending_set_request_data(pending, 0, req);
845         tcore_pending_set_response_callback(pending, on_response_set_flight_mode, hal);
846         tcore_pending_link_user_request(pending, ur);
847         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
848
849         tcore_hal_send_request(hal, pending);
850
851         return TCORE_RETURN_SUCCESS;
852 }
853
854
855 static struct tcore_modem_operations modem_ops =
856 {
857         .power_on = power_on,
858         .power_off = power_off,
859         .power_reset = power_reset,
860         .set_flight_mode = set_flight_mode,
861         .get_imei = get_imei,
862         .get_version = get_version,
863         .get_sn = NULL,
864         .dun_pin_ctrl = NULL,
865 };
866
867 gboolean s_modem_init(TcorePlugin *p, TcoreHal *h)
868 {
869         CoreObject *o;
870         GQueue *work_queue;
871         TelMiscVersionInformation *vi_property;
872         TelMiscSNInformation *imei_property;
873         TelMiscSNInformation *sn_property;
874
875         o = tcore_modem_new(p, "modem", &modem_ops, h);
876         if (!o)
877                 return FALSE;
878
879         work_queue = g_queue_new();
880         tcore_object_link_user_data(o, work_queue);
881
882         vi_property = calloc(sizeof(TelMiscVersionInformation), 1);
883         tcore_plugin_link_property(p, "VERSION", vi_property);
884
885         imei_property = calloc(sizeof(TelMiscSNInformation), 1);
886         tcore_plugin_link_property(p, "IMEI", imei_property);
887
888         sn_property = calloc(sizeof(TelMiscSNInformation), 1);
889         tcore_plugin_link_property(p, "SN", sn_property);
890
891         tcore_object_add_callback(o, "+XSIM", on_event_bootup_sim_status, NULL);
892         return TRUE;
893 }
894
895 void s_modem_exit(TcorePlugin *p)
896 {
897         CoreObject *o;
898         GQueue *work_queue;
899         TelMiscVersionInformation *vi_property;
900         TelMiscSNInformation *imei_property;
901         TelMiscSNInformation *sn_property;
902
903         if (!p)
904                 return;
905
906         o = tcore_plugin_ref_core_object(p, "modem");
907
908         work_queue = tcore_object_ref_user_data(o);
909         g_queue_free(work_queue);
910
911         vi_property = tcore_plugin_ref_property(p, "VERSION");
912         if (vi_property)
913                 free(vi_property);
914
915         imei_property = tcore_plugin_ref_property(p, "IMEI");
916         if (imei_property)
917                 free(imei_property);
918
919         sn_property = tcore_plugin_ref_property(p, "SN");
920         if (sn_property)
921                 free(sn_property);
922
923         tcore_modem_free(o);
924 }
925
926 gboolean s_modem_send_poweron(TcorePlugin *p)
927 {
928         TcoreHal* hal;
929         TcoreATRequest *req;
930         TcorePending *pending = NULL;
931         CoreObject *o;
932
933         o = tcore_plugin_ref_core_object(p, "modem");
934         hal = tcore_object_get_hal(o);
935         /* HAL has type itself,
936          * e.g.) TCORE_HAL_MODE_AT
937          */
938         pending = tcore_pending_new(o, 0);
939
940         /* Set Metainfo into TcorePending directly
941          * using TcoreATRequest
942          * command type: e.g.) SINGLELINE
943          * response prefix
944          */
945
946         req = tcore_at_request_new("AT+CPAS", "+CPAS", TCORE_AT_SINGLELINE);
947
948         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
949
950         tcore_pending_set_timeout(pending, 10);
951         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);    
952         tcore_pending_set_timeout_callback(pending, on_timeout_modem_poweron, hal);
953         
954         tcore_pending_set_request_data(pending, 0, req);
955         tcore_pending_set_response_callback(pending, on_response_poweron, hal);
956         tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
957
958         tcore_hal_send_request(hal, pending);
959
960         return TRUE;
961 }