4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Kyoungyoup Park <gynaru.park@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
34 #include <user_request.h>
35 #include <core_object.h>
43 #define IMC_MODEM_PLUGIN_NAME "imc-plugin.so"
45 #define IMC_CMUX_MAX_CHANNELS 7
46 #define IMC_CMUX_MAX_BUFFER_SIZE 2048
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
56 /* Maximum Core objects per Logical HAL (indirectly per Channel) */
57 #define MAX_CORE_OBJECTS_PER_CHANNEL 3
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"
62 * List of supported Core Object types
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
71 * Channel 6 - NETWORK & GPS
72 * Channel 7 - MODEM & PS
75 supported_modules[IMC_CMUX_MAX_CHANNELS+1][MAX_CORE_OBJECTS_PER_CHANNEL] =
78 * Channel 0 - CMUX Control Channel
79 * No Core Objects would be assigned to this channel
83 {CORE_OBJECT_TYPE_CALL, CORE_OBJECT_TYPE_SS, 0},
85 {CORE_OBJECT_TYPE_SIM, CORE_OBJECT_TYPE_PHONEBOOK, 0},
87 {CORE_OBJECT_TYPE_SAT, CORE_OBJECT_TYPE_SAP, 0},
89 {CORE_OBJECT_TYPE_SMS, 0, 0},
91 {CORE_OBJECT_TYPE_PS, 0, 0},
93 {CORE_OBJECT_TYPE_NETWORK, CORE_OBJECT_TYPE_GPS, 0},
95 {CORE_OBJECT_TYPE_MODEM, 0, 0},
98 static gboolean _check_cp_poweron(TcoreHal *hal);
99 static void _send_enable_logging_command(TcoreHal *hal);
101 static void _on_confirmation_send_message(TcorePending *pending,
102 gboolean result, void *user_data)
104 dbg("Message send confirmation");
106 if (result == FALSE) { /* Fail */
112 static void _assign_objects_to_hal(int channel_id, TcoreHal *hal, TcoreHal *phy_hal)
114 ImcmodemCustomData *custom_data;
124 if (phy_hal == NULL) {
125 err("Physical HAL is NULL");
129 custom_data = tcore_hal_ref_user_data(phy_hal);
130 if (custom_data == NULL) {
131 err("custom_data is NULL");
135 modem = custom_data->modem;
137 for (i = 0 ; i < MAX_CORE_OBJECTS_PER_CHANNEL ; i++) {
138 if (supported_modules[channel_id][i] == 0)
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);
145 dbg("Core Object Type: [0x%x] - Success");
147 err("Core Object Type: [0x%x] - Fail");
152 static void _on_cmux_setup_complete(gpointer user_data)
155 TcoreHal *hal = user_data;
156 ImcmodemCustomData *custom_data;
157 unsigned int slot_cnt = 1;
159 dbg("MUX Setup - COMPLETE");
166 custom_data = tcore_hal_ref_user_data(hal);
167 if (custom_data == NULL) {
168 err("custom_data is NULL");
172 s = tcore_plugin_ref_server(tcore_hal_ref_plugin(hal));
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");
179 tcore_server_send_notification(s, NULL,
180 TNOTI_SERVER_ADDED_MODEM_PLUGIN_COMPLETED,
181 sizeof(slot_cnt), &slot_cnt);
184 static void _on_cmux_channel_setup(int channel_id,
185 TcoreHal *hal, gpointer user_data)
189 if ((hal == NULL) || (user_data == NULL))
192 if ((channel_id == 0) || (channel_id > IMC_CMUX_MAX_CHANNELS)) {
193 err("Control Channel");
198 plugin = tcore_hal_ref_plugin(hal);
200 dbg("Channel ID: [%d] Logical HAL: [0x%x]", channel_id, hal);
202 /* Assign specifc Core Object types to the Logical HAL (CMUX Channel) */
203 _assign_objects_to_hal(channel_id, hal, phy_hal);
205 /* Set HAL state to Power ON (TRUE) */
206 tcore_hal_set_power_state(hal, TRUE);
207 dbg("HAL Power State: Power ON");
210 static void _on_response_cmux_init(TcorePending *p, int data_len,
211 const void *data, void *user_data)
213 const TcoreATResponse *resp = data;
214 TcoreHal *hal = user_data;
216 if ((resp != NULL) && resp->success) {
218 dbg("Initialize CMUX - [OK]");
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);
227 err("Initialize CMUX - [NOK]");
231 static void _on_response_enable_logging(TcorePending *p,
232 int data_len, const void *data, void *user_data)
234 const TcoreATResponse *resp = data;
235 TcoreHal *hal = user_data;
238 if ((resp != NULL) && resp->success) {
239 dbg("Enable CP logging - [OK]");
241 err("Enable CP logging - [NOK]");
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);
249 dbg("Successfully sent CMUX init to CP");
253 static void _on_timeout_check_cp_poweron(TcorePending *p, void *user_data)
255 TcoreHal *hal = user_data;
256 unsigned int data_len = 0;
257 char *data = "AT+CPAS";
259 data_len = sizeof(data);
261 dbg("Resending Command: [%s] Command Length: [%d]", data, data_len);
264 * Retransmit 1st AT command (AT+CPAS) directly via HAL without disturbing
266 * HAL was passed as user_data, re-using it
268 tcore_hal_send_data(hal, data_len, (void *)data);
271 static void _on_response_check_cp_poweron(TcorePending *pending,
272 int data_len, const void *data, void *user_data)
274 const TcoreATResponse *resp = data;
275 TcoreHal *hal = user_data;
277 GSList *tokens = NULL;
279 gboolean bpoweron = FALSE;
284 dbg("Check CP POWER - [OK]");
286 /* Parse AT Response */
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");
296 response = atoi(g_slist_nth_data(tokens, 0));
297 dbg("CPAS State: [%d]", 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!!!");
308 case IMC_AT_CPAS_RESULT_UNAVAIL:
309 case IMC_AT_CPAS_RESULT_UNKNOWN:
311 err("Value is Unvailable/Unknown - but CP responded - proceed with Power ON!!!");
316 dbg("Check CP POWER - [NOK]");
321 tcore_at_tok_free(tokens);
323 if (bpoweron == TRUE) {
324 dbg("CP Power ON received");
327 _send_enable_logging_command(hal);
329 err("CP is not ready, send CPAS again");
330 _check_cp_poweron(hal);
335 static void _send_enable_logging_command(TcoreHal *hal)
337 TcoreATRequest *at_req = NULL;
338 TcorePending *pending = NULL;
340 dbg("Sending Trace enabling command for CP logging");
342 /* Create Pending request */
343 pending = tcore_pending_new(NULL, 0);
345 /* Create AT Request */
346 at_req = tcore_at_request_new(IMCMODEM_AT_CMD_XTRACE_ENABLE,
347 NULL, TCORE_AT_NO_RESULT);
349 if (at_req == NULL) {
350 tcore_pending_free(pending);
354 dbg("AT-Command: [%s] Prefix(if any): [%s] Command length: [%d]",
355 at_req->cmd, at_req->prefix, strlen(at_req->cmd));
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);
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);
367 err("Failed to send Trace logging command");
369 dbg("Successfully sent Trace logging command");
373 static gboolean _check_cp_poweron(TcoreHal *hal)
375 TcoreATRequest *at_req;
376 TcorePending *pending = NULL;
378 /* Create Pending request */
379 pending = tcore_pending_new(NULL, 0);
381 /* Create AT Request */
382 at_req = tcore_at_request_new("AT+CPAS", "+CPAS:", TCORE_AT_SINGLELINE);
384 if (at_req == NULL) {
385 tcore_pending_free(pending);
389 dbg("AT-Command: [%s] Prefix(if any): [%s] Command length: [%d]",
390 at_req->cmd, at_req->prefix, strlen(at_req->cmd));
392 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
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);
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);
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);
408 err("Failed to send CPAS");
411 dbg("Successfully sent CPAS");
416 void config_check_cp_power(TcoreHal *hal)
424 ret = _check_cp_poweron(hal);
426 dbg("Successfully sent check CP Power ON command");
428 err("Failed to send check CP Power ON command");