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