Fix SVACE issue
[platform/core/telephony/tel-plugin-imc.git] / src / imc_sat.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Chandan Swarup Patra <chandan.sp@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <glib.h>
25 #include <tcore.h>
26 #include <hal.h>
27 #include <core_object.h>
28 #include <plugin.h>
29 #include <queue.h>
30 #include <server.h>
31 #include <co_sat.h>
32 #include <user_request.h>
33 #include <at.h>
34
35 #include "imc_common.h"
36 #include "imc_sat.h"
37 #define ENVELOPE_CMD_LEN        256
38
39 static TReturn imc_terminal_response(CoreObject *o, UserRequest *ur);
40 static void on_confirmation_sat_message_send(TcorePending *p, gboolean result, void *user_data);      /* from Kernel */
41
42 static void on_confirmation_sat_message_send(TcorePending *p, gboolean result, void *user_data)
43 {
44         dbg("on_confirmation_modem_message_send - msg out from queue.\n");
45
46         if (result == FALSE) {
47                 /* Fail */
48                 dbg("SEND FAIL");
49         } else {
50                 dbg("SEND OK");
51         }
52 }
53
54 static gboolean on_response_terminal_response_confirm(CoreObject *o, const void *event_info, void *user_data)
55 {
56         dbg("Function Entry");
57         return TRUE;
58         dbg("Function Exit");
59 }
60
61 static gboolean on_event_sat_proactive_command(CoreObject *o, const void *event_info, void *user_data)
62 {
63         struct tcore_sat_proactive_command decoded_data;
64         struct tnoti_sat_proactive_ind proactive_noti;
65         int len_proactive_cmd = 0;
66         GSList *lines = NULL;
67         GSList *tokens = NULL;
68         char *line = NULL;
69         char *hexData = NULL;
70         char *tmp = NULL;
71         char *recordData = NULL;
72
73         dbg("Function Entry");
74
75         memset(&proactive_noti, 0x00, sizeof(struct tnoti_sat_proactive_ind));
76         memset(&decoded_data, 0x00, sizeof(struct tcore_sat_proactive_command));
77         lines = (GSList *) event_info;
78         line = (char *) lines->data;
79         tokens = tcore_at_tok_new(line);
80         if (g_slist_length(tokens) != 1) {
81                 err("Invalid message");
82                 tcore_at_tok_free(tokens);
83                 return FALSE;
84         }
85
86         hexData = (char *)g_slist_nth_data(tokens, 0);
87         dbg("SAT data: [%s] SAT data length: [%d]", hexData, strlen(hexData));
88
89         tmp = tcore_at_tok_extract(hexData);
90         recordData = util_hexStringToBytes(tmp);
91         if (!recordData) {
92                 err("util_hexStringToBytes Failed!!");
93                 tcore_at_tok_free(tokens);
94                 return FALSE;
95         }
96         dbg("recordData: %x", recordData);
97         g_free(tmp);
98         tcore_util_hex_dump("    ", strlen(hexData) / 2, recordData);
99         len_proactive_cmd = strlen(recordData);
100         dbg("len_proactive_cmd = %d", len_proactive_cmd);
101         tcore_sat_decode_proactive_command((unsigned char *) recordData, (strlen(hexData) / 2) - 1, &decoded_data);
102         g_free(recordData);
103
104         proactive_noti.cmd_number = decoded_data.cmd_num;
105         proactive_noti.cmd_type = decoded_data.cmd_type;
106
107         switch (decoded_data.cmd_type) {
108         case SAT_PROATV_CMD_DISPLAY_TEXT:
109                 dbg("decoded command is display text!!");
110                 memcpy(&proactive_noti.proactive_ind_data.display_text, &decoded_data.data.display_text, sizeof(struct tel_sat_display_text_tlv));
111                 break;
112
113         case SAT_PROATV_CMD_GET_INKEY:
114                 dbg("decoded command is get inkey!!");
115                 memcpy(&proactive_noti.proactive_ind_data.get_inkey, &decoded_data.data.get_inkey, sizeof(struct tel_sat_get_inkey_tlv));
116                 break;
117
118         case SAT_PROATV_CMD_GET_INPUT:
119                 dbg("decoded command is get input!!");
120                 memcpy(&proactive_noti.proactive_ind_data.get_input, &decoded_data.data.get_input, sizeof(struct tel_sat_get_input_tlv));
121                 break;
122
123         case SAT_PROATV_CMD_MORE_TIME:
124                 dbg("decoded command is more time!!");
125                 memcpy(&proactive_noti.proactive_ind_data.more_time, &decoded_data.data.more_time, sizeof(struct tel_sat_more_time_tlv));
126                 break;
127
128         case SAT_PROATV_CMD_PLAY_TONE:
129                 dbg("decoded command is play tone!!");
130                 memcpy(&proactive_noti.proactive_ind_data.play_tone, &decoded_data.data.play_tone, sizeof(struct tel_sat_play_tone_tlv));
131                 break;
132
133         case SAT_PROATV_CMD_SETUP_MENU:
134                 dbg("decoded command is SETUP MENU!!");
135                 memcpy(&proactive_noti.proactive_ind_data.setup_menu, &decoded_data.data.setup_menu, sizeof(struct tel_sat_setup_menu_tlv));
136                 break;
137
138         case SAT_PROATV_CMD_SELECT_ITEM:
139                 dbg("decoded command is select item!!");
140                 memcpy(&proactive_noti.proactive_ind_data.select_item, &decoded_data.data.select_item, sizeof(struct tel_sat_select_item_tlv));
141                 break;
142
143         case SAT_PROATV_CMD_SEND_SMS:
144                 dbg("decoded command is send sms!!");
145                 memcpy(&proactive_noti.proactive_ind_data.send_sms, &decoded_data.data.send_sms, sizeof(struct tel_sat_send_sms_tlv));
146                 break;
147
148         case SAT_PROATV_CMD_SEND_SS:
149                 dbg("decoded command is send ss!!");
150                 memcpy(&proactive_noti.proactive_ind_data.send_ss, &decoded_data.data.send_ss, sizeof(struct tel_sat_send_ss_tlv));
151                 break;
152
153         case SAT_PROATV_CMD_SEND_USSD:
154                 dbg("decoded command is send ussd!!");
155                 memcpy(&proactive_noti.proactive_ind_data.send_ussd, &decoded_data.data.send_ussd, sizeof(struct tel_sat_send_ussd_tlv));
156                 break;
157
158         case SAT_PROATV_CMD_SETUP_CALL:
159                 dbg("decoded command is setup call!!");
160                 memcpy(&proactive_noti.proactive_ind_data.setup_call, &decoded_data.data.setup_call, sizeof(struct tel_sat_setup_call_tlv));
161                 break;
162
163         case SAT_PROATV_CMD_REFRESH:
164                 dbg("decoded command is refresh");
165                 memcpy(&proactive_noti.proactive_ind_data.refresh, &decoded_data.data.refresh, sizeof(struct tel_sat_refresh_tlv));
166                 break;
167
168         case SAT_PROATV_CMD_PROVIDE_LOCAL_INFO:
169                 dbg("decoded command is provide local info");
170                 memcpy(&proactive_noti.proactive_ind_data.provide_local_info, &decoded_data.data.provide_local_info, sizeof(struct tel_sat_provide_local_info_tlv));
171                 break;
172
173         case SAT_PROATV_CMD_SETUP_EVENT_LIST:
174                 dbg("decoded command is setup event list!!");
175                 memcpy(&proactive_noti.proactive_ind_data.setup_event_list, &decoded_data.data.setup_event_list, sizeof(struct tel_sat_setup_event_list_tlv));
176                 break;
177
178         case SAT_PROATV_CMD_SETUP_IDLE_MODE_TEXT:
179                 dbg("decoded command is setup idle mode text");
180                 memcpy(&proactive_noti.proactive_ind_data.setup_idle_mode_text, &decoded_data.data.setup_idle_mode_text, sizeof(struct tel_sat_setup_idle_mode_text_tlv));
181                 break;
182
183         case SAT_PROATV_CMD_SEND_DTMF:
184                 dbg("decoded command is send dtmf");
185                 memcpy(&proactive_noti.proactive_ind_data.send_dtmf, &decoded_data.data.send_dtmf, sizeof(struct tel_sat_send_dtmf_tlv));
186                 break;
187
188         case SAT_PROATV_CMD_LANGUAGE_NOTIFICATION:
189                 dbg("decoded command is language notification");
190                 memcpy(&proactive_noti.proactive_ind_data.language_notification, &decoded_data.data.language_notification, sizeof(struct tel_sat_language_notification_tlv));
191                 break;
192
193         case SAT_PROATV_CMD_LAUNCH_BROWSER:
194                 dbg("decoded command is launch browser");
195                 memcpy(&proactive_noti.proactive_ind_data.launch_browser, &decoded_data.data.launch_browser, sizeof(struct tel_sat_launch_browser_tlv));
196                 break;
197
198         case SAT_PROATV_CMD_OPEN_CHANNEL:
199                 dbg("decoded command is open channel!!");
200                 memcpy(&proactive_noti.proactive_ind_data.open_channel, &decoded_data.data.open_channel, sizeof(struct tel_sat_open_channel_tlv));
201                 break;
202
203         case SAT_PROATV_CMD_CLOSE_CHANNEL:
204                 dbg("decoded command is close channel!!");
205                 memcpy(&proactive_noti.proactive_ind_data.close_channel, &decoded_data.data.close_channel, sizeof(struct tel_sat_close_channel_tlv));
206                 break;
207
208         case SAT_PROATV_CMD_RECEIVE_DATA:
209                 dbg("decoded command is receive data!!");
210                 memcpy(&proactive_noti.proactive_ind_data.receive_data, &decoded_data.data.receive_data, sizeof(struct tel_sat_receive_channel_tlv));
211                 break;
212
213         case SAT_PROATV_CMD_SEND_DATA:
214                 dbg("decoded command is send data!!");
215                 memcpy(&proactive_noti.proactive_ind_data.send_data, &decoded_data.data.send_data, sizeof(struct tel_sat_send_channel_tlv));
216                 break;
217
218         case SAT_PROATV_CMD_GET_CHANNEL_STATUS:
219                 dbg("decoded command is get channel status!!");
220                 memcpy(&proactive_noti.proactive_ind_data.get_channel_status, &decoded_data.data.get_channel_status, sizeof(struct tel_sat_get_channel_status_tlv));
221                 break;
222
223         default:
224                 dbg("wrong input");
225                 break;
226         }
227         if (decoded_data.cmd_type == SAT_PROATV_CMD_REFRESH) {
228                 /*Not supported*/
229                 dbg("Not suported Proactive command");
230                 return FALSE;
231         }
232         tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_SAT_PROACTIVE_CMD,
233                                                                    sizeof(struct tnoti_sat_proactive_ind), &proactive_noti);
234         tcore_at_tok_free(tokens);
235         dbg("Function Exit");
236         return TRUE;
237 }
238
239 static void on_response_envelop_cmd(TcorePending *p, int data_len, const void *data, void *user_data)
240 {
241         const TcoreATResponse *resp = data;
242         UserRequest *ur = NULL;
243         CoreObject *o = NULL;
244         const struct                treq_sat_envelop_cmd_data *req_data = NULL;
245         GSList *tokens = NULL;
246         struct                      tresp_sat_envelop_data res;
247         const char *line = NULL;
248         int sw2 = -1;
249
250         ur = tcore_pending_ref_user_request(p);
251         req_data = tcore_user_request_ref_data(ur, NULL);
252         o = tcore_pending_ref_core_object(p);
253
254         if (!req_data) {
255                 dbg("request data is NULL");
256                 return;
257         }
258         memset(&res, 0, sizeof(struct tresp_sat_envelop_data));
259
260         res.sub_cmd = req_data->sub_cmd;
261
262         if (resp->success > 0) {
263                 dbg("RESPONSE OK");
264                 if (resp->lines) {
265                         line = (const char *) resp->lines->data;
266                         tokens = tcore_at_tok_new(line);
267                         if (g_slist_length(tokens) < 1) {
268                                 msg("invalid message");
269                                 tcore_at_tok_free(tokens);
270                                 return;
271                         }
272                 }
273                 res.result = 0x8000;
274                 res.envelop_resp = ENVELOPE_SUCCESS;
275                 dbg("RESPONSE OK 3");
276                 if (NULL != g_slist_nth_data(tokens, 1)) {
277                         sw2 = atoi(g_slist_nth_data(tokens, 1));
278                         dbg("RESPONSE OK 4");
279                         if (sw2 == 0) {
280                                 dbg("RESPONSE OK 5");
281                                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_SAT_SESSION_END, 0, NULL);
282                         }
283                 }
284         } else {
285                 dbg("RESPONSE NOK");
286                 res.result = -1;
287                 res.envelop_resp = ENVELOPE_FAILED;
288         }
289
290         if (ur)
291                 tcore_user_request_send_response(ur, TRESP_SAT_REQ_ENVELOPE, sizeof(struct tresp_sat_envelop_data), &res);
292
293         tcore_at_tok_free(tokens);
294         dbg(" Function exit");
295 }
296
297
298 static void on_response_terminal_response(TcorePending *p, int data_len, const void *data, void *user_data)
299 {
300         UserRequest *ur = NULL;
301         CoreObject *o = NULL;
302         const TcoreATResponse *resp = data;
303         gpointer tmp = NULL;
304
305         dbg("Function Entry");
306
307         if (resp->success > 0) {
308                 dbg("RESPONSE OK");
309                 dbg(" resp->success = %d", resp->success);
310                 ur = tcore_pending_ref_user_request(p);
311                 tmp = (gpointer) tcore_user_request_ref_communicator(ur);
312                 if (!ur || !tmp) {
313                         dbg("error - current ur is NULL");
314                         return;
315                 }
316
317                 o = tcore_pending_ref_core_object(p);
318                 if (!o)
319                         dbg("error - current sat core is NULL");
320                 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_SAT_SESSION_END, 0, NULL);
321         }
322         dbg("Function Exit");
323 }
324
325 static TReturn imc_envelope(CoreObject *o, UserRequest *ur)
326 {
327         TcoreHal *hal;
328         TcoreATRequest *req = NULL;
329         TcorePending *pending = NULL;
330         char *cmd_str = NULL;
331         const struct            treq_sat_envelop_cmd_data *req_data = NULL;
332         int envelope_cmd_len = 0;
333         char envelope_cmd[ENVELOPE_CMD_LEN];
334         int count = 0;
335         char envelope_cmdhex[ENVELOPE_CMD_LEN * 2];
336         char *pbuffer = NULL;
337
338         dbg("Function Entry");
339         memset(&envelope_cmdhex, 0x00, sizeof(envelope_cmdhex));
340         pbuffer = envelope_cmdhex;
341
342         hal = tcore_object_get_hal(o);
343         if (FALSE == tcore_hal_get_power_state(hal)) {
344                 dbg("cp not ready/n");
345                 return TCORE_RETURN_ENOSYS;
346         }
347
348         pending = tcore_pending_new(o, 0);
349         req_data = tcore_user_request_ref_data(ur, NULL);
350         dbg("new pending sub cmd(%d)", req_data->sub_cmd);
351
352         envelope_cmd_len = tcore_sat_encode_envelop_cmd(req_data, (char *) envelope_cmd);
353
354         dbg("envelope_cmd_len %d", envelope_cmd_len);
355         if (envelope_cmd_len == 0)
356                 return TCORE_RETURN_EINVAL;
357
358         for (count = 0; count < envelope_cmd_len; count++) {
359                 dbg("envelope_cmd %02x", (unsigned char)envelope_cmd[count]);
360                 snprintf(pbuffer, 256, "%02x", (unsigned char)envelope_cmd[count]);
361                 pbuffer += 2;
362         }
363         dbg("pbuffer %s", envelope_cmdhex);
364         cmd_str = g_strdup_printf("AT+SATE=\"%s\"", envelope_cmdhex);
365         req = tcore_at_request_new(cmd_str, "+SATE:", TCORE_AT_SINGLELINE);
366         if (req == NULL) {
367                 g_free(cmd_str);
368                 tcore_pending_free(pending);
369                 return TCORE_RETURN_FAILURE;
370         }
371
372         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
373
374         tcore_pending_set_request_data(pending, 0, req);
375         tcore_pending_set_response_callback(pending, on_response_envelop_cmd, hal);
376         tcore_pending_link_user_request(pending, ur);
377         tcore_pending_set_send_callback(pending, on_confirmation_sat_message_send, NULL);
378         tcore_hal_send_request(hal, pending);
379
380         g_free(cmd_str);
381         dbg("Function Exit");
382         return TCORE_RETURN_SUCCESS;
383 }
384
385 static TReturn imc_terminal_response(CoreObject *o, UserRequest *ur)
386 {
387         TcoreHal *hal = NULL;
388         TcoreATRequest *req = NULL;
389         TcorePending *pending = NULL;
390         char *cmd_str = NULL;
391         const struct            treq_sat_terminal_rsp_data *req_data = NULL;
392         int proactive_resp_len = 0;
393         char proactive_resp[ENVELOPE_CMD_LEN];
394         char proactive_resphex[ENVELOPE_CMD_LEN * 2];
395         int i = 0;
396         char *hexString = NULL;
397
398         dbg("Function Entry");
399         memset(&proactive_resphex, 0x00, sizeof(proactive_resphex));
400         hal = tcore_object_get_hal(o);
401         if (FALSE == tcore_hal_get_power_state(hal)) {
402                 dbg("cp not ready/n");
403                 return TCORE_RETURN_ENOSYS;
404         }
405
406         pending = tcore_pending_new(o, 0);
407         req_data = tcore_user_request_ref_data(ur, NULL);
408
409         proactive_resp_len = tcore_sat_encode_terminal_response(req_data, (char *) proactive_resp);
410         dbg("proactive_resp %s", proactive_resp);
411         dbg("proactive_resp length %d", strlen(proactive_resp));
412         if (proactive_resp_len == 0) {
413                 tcore_pending_free(pending);
414                 return TCORE_RETURN_EINVAL;
415         }
416         hexString = calloc((proactive_resp_len * 2) + 1, 1);
417         if (hexString == NULL) {
418                 tcore_pending_free(pending);
419                 return TCORE_RETURN_FAILURE;
420         }
421
422         for (i = 0; i < proactive_resp_len * 2; i += 2) {
423                 char value = 0;
424                 value = (proactive_resp[i / 2] & 0xf0) >> 4;
425                 if (value < 0xA)
426                         hexString[i] = ((proactive_resp[i / 2] & 0xf0) >> 4) + '0';
427                 else
428                         hexString[i] = ((proactive_resp[i / 2] & 0xf0) >> 4) + 'A' - 10;
429
430                 value = proactive_resp[i / 2] & 0x0f;
431                 if (value < 0xA)
432                         hexString[i + 1] = (proactive_resp[i / 2] & 0x0f) + '0';
433                 else
434                         hexString[i + 1] = (proactive_resp[i / 2] & 0x0f) + 'A' - 10;
435         }
436
437         dbg("hexString %s", hexString);
438         cmd_str = g_strdup_printf("AT+SATR=\"%s\"", hexString);
439
440         req = tcore_at_request_new(cmd_str, NULL, TCORE_AT_NO_RESULT);
441         if (req == NULL) {
442                 g_free(cmd_str);
443                 g_free(hexString);
444                 tcore_pending_free(pending);
445                 return TCORE_RETURN_FAILURE;
446         }
447
448         dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
449
450         tcore_pending_set_request_data(pending, 0, req);
451         tcore_pending_set_response_callback(pending, on_response_terminal_response, hal);
452         tcore_pending_link_user_request(pending, ur);
453         tcore_pending_set_send_callback(pending, on_confirmation_sat_message_send, NULL);
454         tcore_hal_send_request(hal, pending);
455
456         g_free(cmd_str);
457         g_free(hexString);
458         dbg("Function Exit");
459         return TCORE_RETURN_SUCCESS;
460 }
461
462 static struct tcore_sat_operations sat_ops = {
463         .envelope = imc_envelope,
464         .terminal_response = imc_terminal_response,
465 };
466
467 gboolean imc_sat_init(TcorePlugin *cp, CoreObject *co_sat)
468 {
469         dbg("Entry");
470
471         /* Set operations */
472         tcore_sat_set_ops(co_sat, &sat_ops, TCORE_OPS_TYPE_CP);
473
474         tcore_object_add_callback(co_sat, "+SATI", on_event_sat_proactive_command, NULL);
475         tcore_object_add_callback(co_sat, "+SATN", on_event_sat_proactive_command, NULL);
476         tcore_object_add_callback(co_sat, "+SATF", on_response_terminal_response_confirm, NULL);
477
478         dbg("Exit");
479
480         return TRUE;
481 }
482
483 void imc_sat_exit(TcorePlugin *cp, CoreObject *co_sat)
484 {
485         dbg("Exit");
486 }