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