tizen 2.3.1 release
[framework/telephony/tel-plugin-imcmodem.git] / src / config.c
1 /*
2  * tel-plugin-imcmodem
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Kyoungyoup Park <gynaru.park@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 <string.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <time.h>
27
28 #include <glib.h>
29
30 #include <tcore.h>
31 #include <server.h>
32 #include <plugin.h>
33 #include <storage.h>
34 #include <user_request.h>
35 #include <core_object.h>
36 #include <hal.h>
37 #include <at.h>
38 #include <mux.h>
39
40 #include "imcmodem.h"
41 #include "config.h"
42
43 #define IMC_MODEM_PLUGIN_NAME           "imc-plugin.so"
44
45 #define IMC_CMUX_MAX_CHANNELS           7
46 #define IMC_CMUX_MAX_BUFFER_SIZE                2048
47
48 /* CP States */
49 #define IMC_AT_CPAS_RESULT_READY                0
50 #define IMC_AT_CPAS_RESULT_UNAVAIL              1
51 #define IMC_AT_CPAS_RESULT_UNKNOWN              2
52 #define IMC_AT_CPAS_RESULT_RINGING              3
53 #define IMC_AT_CPAS_RESULT_CALL_PROGRESS        4
54 #define IMC_AT_CPAS_RESULT_ASLEEP               5
55
56 /* Maximum Core objects per Logical HAL (indirectly per Channel) */
57 #define MAX_CORE_OBJECTS_PER_CHANNEL            3
58
59 #define IMCMODEM_AT_CMD_XTRACE_ENABLE   "at+xsystrace=1,\"digrf=1;bb_sw=1;3g_sw=1\",\"digrf=0x84\",\"oct=4\";+xsystrace=11;+trace=1"
60
61 /*
62  * List of supported Core Object types
63  *
64  * CMUX Channels [0-7] -
65  * Channel 0 - Control Channel for CMUX
66  * Channel 1 - CALL & SS
67  * Channel 2 - SIM & PHONEBOOK
68  * Channel 3 - SAT & SAP
69  * Channel 4 - SMS
70  * Channel 5 - PS
71  * Channel 6 - NETWORK & GPS
72  * Channel 7 - MODEM & PS
73  */
74 unsigned int
75         supported_modules[IMC_CMUX_MAX_CHANNELS+1][MAX_CORE_OBJECTS_PER_CHANNEL] =
76 {
77         /*
78          * Channel 0 - CMUX Control Channel
79          * No Core Objects would be assigned to this channel
80          */
81         {0, 0, 0},
82         /* Channel 1 */
83         {CORE_OBJECT_TYPE_CALL, CORE_OBJECT_TYPE_SS, 0},
84         /* Channel 2 */
85         {CORE_OBJECT_TYPE_SIM, CORE_OBJECT_TYPE_PHONEBOOK, 0},
86         /* Channel 3 */
87         {CORE_OBJECT_TYPE_SAT, CORE_OBJECT_TYPE_SAP, 0},
88         /* Channel 4 */
89         {CORE_OBJECT_TYPE_SMS, 0, 0},
90         /* Channel 5 */
91         {CORE_OBJECT_TYPE_PS, 0, 0},
92         /* Channel 6 */
93         {CORE_OBJECT_TYPE_NETWORK, CORE_OBJECT_TYPE_GPS, 0},
94         /* Channel 7 */
95         {CORE_OBJECT_TYPE_MODEM, 0, 0},
96 };
97
98 static gboolean _check_cp_poweron(TcoreHal *hal);
99 static void _send_enable_logging_command(TcoreHal *hal);
100
101 static void _on_confirmation_send_message(TcorePending *pending,
102         gboolean result, void *user_data)
103 {
104         dbg("Message send confirmation");
105
106         if (result == FALSE) {          /* Fail */
107                 dbg("SEND FAIL");
108         } else {
109                 dbg("SEND OK");
110         }
111 }
112 static void _assign_objects_to_hal(int channel_id, TcoreHal *hal, TcoreHal *phy_hal)
113 {
114         ImcmodemCustomData *custom_data;
115         TcoreModem *modem;
116         gboolean ret;
117         int i;
118
119         if (hal == NULL) {
120                 err("HAL is NULL");
121                 return;
122         }
123
124         if (phy_hal == NULL) {
125                 err("Physical HAL is NULL");
126                 return;
127         }
128
129         custom_data = tcore_hal_ref_user_data(phy_hal);
130         if (custom_data == NULL) {
131                 err("custom_data is NULL");
132                 return;
133         }
134
135         modem = custom_data->modem;
136
137         for (i = 0 ; i < MAX_CORE_OBJECTS_PER_CHANNEL ; i++) {
138                 if (supported_modules[channel_id][i] == 0)
139                         continue;
140
141                 /* Add Core Object type for specific 'hal' */
142                 ret = tcore_server_add_cp_mapping_tbl_entry(modem,
143                                 supported_modules[channel_id][i], hal);
144                 if (ret == TRUE) {
145                         dbg("Core Object Type: [0x%x] - Success");
146                 } else {
147                         err("Core Object Type: [0x%x] - Fail");
148                 }
149         }
150 }
151
152 static void _on_cmux_setup_complete(gpointer user_data)
153 {
154         Server *s;
155         TcoreHal *hal = user_data;
156         ImcmodemCustomData *custom_data;
157         unsigned int slot_cnt = 1;
158
159         dbg("MUX Setup - COMPLETE");
160
161         if (hal == NULL) {
162                 err("HAL is NULL");
163                 return;
164         }
165
166         custom_data = tcore_hal_ref_user_data(hal);
167         if (custom_data == NULL) {
168                 err("custom_data is NULL");
169                 return;
170         }
171
172         s = tcore_plugin_ref_server(tcore_hal_ref_plugin(hal));
173
174         /* Load Modem Plug-in */
175         tcore_server_load_modem_plugin(s,
176                 custom_data->modem, IMC_MODEM_PLUGIN_NAME);
177         dbg("Modem plug-in loaded");
178
179         tcore_server_send_notification(s, NULL,
180                         TNOTI_SERVER_ADDED_MODEM_PLUGIN_COMPLETED,
181                         sizeof(slot_cnt), &slot_cnt);
182 }
183
184 static void _on_cmux_channel_setup(int channel_id,
185         TcoreHal *hal, gpointer user_data)
186 {
187         TcorePlugin *plugin;
188         TcoreHal *phy_hal;
189         if ((hal == NULL) || (user_data == NULL))
190                 return;
191
192         if ((channel_id == 0) || (channel_id > IMC_CMUX_MAX_CHANNELS)) {
193                 err("Control Channel");
194                 return;
195         }
196
197         phy_hal = user_data;
198         plugin = tcore_hal_ref_plugin(hal);
199
200         dbg("Channel ID: [%d] Logical HAL: [0x%x]", channel_id, hal);
201
202         /* Assign specifc Core Object types to the Logical HAL (CMUX Channel) */
203         _assign_objects_to_hal(channel_id, hal, phy_hal);
204
205         /* Set HAL state to Power ON (TRUE) */
206         tcore_hal_set_power_state(hal, TRUE);
207         dbg("HAL Power State: Power ON");
208 }
209
210 static void _on_response_cmux_init(TcorePending *p, int data_len,
211         const void *data, void *user_data)
212 {
213         const TcoreATResponse *resp = data;
214         TcoreHal *hal = user_data;
215
216         if ((resp != NULL) && resp->success) {
217                 TReturn ret;
218                 dbg("Initialize CMUX - [OK]");
219
220                 /* Setup Internal CMUX */
221                 ret = tcore_cmux_setup_internal_mux(CMUX_MODE_BASIC,
222                                         IMC_CMUX_MAX_CHANNELS,
223                                         IMC_CMUX_MAX_BUFFER_SIZE, hal,
224                                         _on_cmux_channel_setup, hal,
225                                         _on_cmux_setup_complete, hal);
226         } else {
227                 err("Initialize CMUX - [NOK]");
228         }
229 }
230
231 static void _on_response_enable_logging(TcorePending *p,
232         int data_len, const void *data, void *user_data)
233 {
234         const TcoreATResponse *resp = data;
235         TcoreHal *hal = user_data;
236         TReturn ret;
237
238         if ((resp != NULL) && resp->success) {
239                 dbg("Enable CP logging - [OK]");
240         } else {
241                 err("Enable CP logging - [NOK]");
242         }
243
244         /* Initialize Internal MUX (CMUX) */
245         ret = tcore_cmux_init(hal, 0, _on_response_cmux_init, hal);
246         if (ret != TCORE_RETURN_SUCCESS) {
247                 err("Failed to initialize CMUX - Error: [0x%x]", ret);
248         } else {
249                 dbg("Successfully sent CMUX init to CP");
250         }
251 }
252
253 static void _on_timeout_check_cp_poweron(TcorePending *p, void *user_data)
254 {
255         TcoreHal *hal = user_data;
256         unsigned int data_len = 0;
257         char *data = "AT+CPAS";
258
259         data_len = sizeof(data);
260
261         dbg("Resending Command: [%s] Command Length: [%d]", data, data_len);
262
263         /*
264          * Retransmit 1st AT command (AT+CPAS) directly via HAL without disturbing
265          * pending queue.
266          * HAL was passed as user_data, re-using it
267          */
268         tcore_hal_send_data(hal, data_len, (void *)data);
269 }
270
271 static void _on_response_check_cp_poweron(TcorePending *pending,
272         int data_len, const void *data, void *user_data)
273 {
274         const TcoreATResponse *resp = data;
275         TcoreHal *hal = user_data;
276
277         GSList *tokens = NULL;
278         const char *line;
279         gboolean bpoweron = FALSE;
280         int response = 0;
281
282         if ((resp != NULL)
283                         && resp->success) {
284                 dbg("Check CP POWER - [OK]");
285
286                 /* Parse AT Response */
287                 if (resp->lines) {
288                         line = (const char *) resp->lines->data;
289                         tokens = tcore_at_tok_new(line);
290                         if (g_slist_length(tokens) != 1) {
291                                 err("Invalid message");
292                                 goto ERROR;
293                         }
294                 }
295
296                 response = atoi(g_slist_nth_data(tokens, 0));
297                 dbg("CPAS State: [%d]", response);
298
299                 switch (response) {
300                 case IMC_AT_CPAS_RESULT_READY:
301                 case IMC_AT_CPAS_RESULT_RINGING:
302                 case IMC_AT_CPAS_RESULT_CALL_PROGRESS:
303                 case IMC_AT_CPAS_RESULT_ASLEEP:
304                         dbg("CP Power ON!!!");
305                         bpoweron = TRUE;
306                 break;
307
308                 case IMC_AT_CPAS_RESULT_UNAVAIL:
309                 case IMC_AT_CPAS_RESULT_UNKNOWN:
310                 default:
311                         err("Value is Unvailable/Unknown - but CP responded - proceed with Power ON!!!");
312                         bpoweron = TRUE;
313                 break;
314                 }
315         } else {
316                 dbg("Check CP POWER - [NOK]");
317         }
318
319 ERROR:
320         /* Free tokens */
321         tcore_at_tok_free(tokens);
322
323         if (bpoweron == TRUE) {
324                 dbg("CP Power ON received");
325
326                 /* Enable Logging */
327                 _send_enable_logging_command(hal);
328         } else {
329                 err("CP is not ready, send CPAS again");
330                 _check_cp_poweron(hal);
331         }
332         return;
333 }
334
335 static void _send_enable_logging_command(TcoreHal *hal)
336 {
337         TcoreATRequest *at_req = NULL;
338         TcorePending *pending = NULL;
339
340         dbg("Sending Trace enabling command for CP logging");
341
342         /* Create Pending request */
343         pending = tcore_pending_new(NULL, 0);
344
345         /* Create AT Request */
346         at_req = tcore_at_request_new(IMCMODEM_AT_CMD_XTRACE_ENABLE,
347                                         NULL, TCORE_AT_NO_RESULT);
348
349         if (at_req  == NULL) {
350                 tcore_pending_free(pending);
351                 return;
352         }
353
354         dbg("AT-Command: [%s] Prefix(if any): [%s] Command length: [%d]",
355                 at_req->cmd, at_req->prefix, strlen(at_req->cmd));
356
357         /* Set request data and register Response and Send callbacks */
358         tcore_pending_set_request_data(pending, 0, at_req);
359         tcore_pending_set_response_callback(pending, _on_response_enable_logging, hal);
360         tcore_pending_set_send_callback(pending, _on_confirmation_send_message, NULL);
361
362         /* Send command to CP */
363         if (tcore_hal_send_request(hal, pending) != TCORE_RETURN_SUCCESS) {
364                 tcore_pending_free(pending);
365                 tcore_at_free(at_req);
366
367                 err("Failed to send Trace logging command");
368         } else {
369                 dbg("Successfully sent Trace logging command");
370         }
371 }
372
373 static gboolean _check_cp_poweron(TcoreHal *hal)
374 {
375         TcoreATRequest *at_req;
376         TcorePending *pending = NULL;
377
378         /* Create Pending request */
379         pending = tcore_pending_new(NULL, 0);
380
381         /* Create AT Request */
382         at_req = tcore_at_request_new("AT+CPAS", "+CPAS:", TCORE_AT_SINGLELINE);
383
384         if (at_req  == NULL) {
385                 tcore_pending_free(pending);
386                 return FALSE;
387         }
388
389         dbg("AT-Command: [%s] Prefix(if any): [%s] Command length: [%d]",
390                 at_req->cmd, at_req->prefix, strlen(at_req->cmd));
391
392         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
393
394         /* Set timeout value and timeout callback */
395         tcore_pending_set_timeout(pending, 10);
396         tcore_pending_set_timeout_callback(pending, _on_timeout_check_cp_poweron, hal);
397
398         /* Set request data and register Response and Send callbacks */
399         tcore_pending_set_request_data(pending, 0, at_req);
400         tcore_pending_set_response_callback(pending, _on_response_check_cp_poweron, hal);
401         tcore_pending_set_send_callback(pending, _on_confirmation_send_message, NULL);
402
403         /* Send command to CP */
404         if (tcore_hal_send_request(hal, pending) != TCORE_RETURN_SUCCESS) {
405                 tcore_pending_free(pending);
406                 tcore_at_free(at_req);
407
408                 err("Failed to send CPAS");
409                 return FALSE;
410         } else {
411                 dbg("Successfully sent CPAS");
412                 return TRUE;
413         }
414 }
415
416 void config_check_cp_power(TcoreHal *hal)
417 {
418         gboolean ret;
419         dbg("Entry");
420
421         if (hal == NULL)
422                 return;
423
424         ret = _check_cp_poweron(hal);
425         if (ret == TRUE) {
426                 dbg("Successfully sent check CP Power ON command");
427         } else {
428                 err("Failed to send check CP Power ON command");
429         }
430 }