4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Harish Bishnoi <hbishnoi@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.
30 #include <core_object.h>
43 #define ID_RESERVED_AT 0x0229
45 #define MAX_VERSION_LEN 32
46 #define TAPI_MISC_ME_SN_LEN_MAX 32
47 #define TAPI_MISC_PRODUCT_CODE_LEN_MAX 32
48 #define TAPI_MISC_MODEL_ID_LEN_MAX 17
49 #define TAPI_MISC_PRL_ERI_VER_LEN_MAX 17
51 #define CPAS_RES_READY 0
52 #define CPAS_RES_UNAVAIL 1
53 #define CPAS_RES_UNKNOWN 2
54 #define CPAS_RES_RINGING 3
55 #define CPAS_RES_CALL_PROGRESS 4
56 #define CPAS_RES_ASLEEP 5
66 CP_STATE_NV_REBUILDING,
71 TAPI_MISC_ME_IMEI = 0x00, /**< 0x00: IMEI, GSM/UMTS device */
72 TAPI_MISC_ME_ESN = 0x01, /**< 0x01: ESN(Electronic Serial Number), It`s essentially run out. CDMA device */
73 TAPI_MISC_ME_MEID = 0x02, /**< 0x02: MEID, This value can have hexa decimal digits. CDMA device */
74 TAPI_MISC_ME_MAX = 0xff /**< 0xff: reserved */
75 } TelMiscSNIndexType_t;
78 TelMiscSNIndexType_t sn_index; /**< serial number index */
79 int sn_len; /**< Length */
80 unsigned char szNumber[TAPI_MISC_ME_SN_LEN_MAX]; /**< Number */
81 } TelMiscSNInformation;
84 * Mobile Equipment Version Information
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 */
88 unsigned char szSwVersion[MAX_VERSION_LEN]; /**< Software version, null termination */
89 unsigned char szHwVersion[MAX_VERSION_LEN]; /**< Hardware version, null termination */
90 unsigned char szRfCalDate[MAX_VERSION_LEN]; /**< Calculation Date, null termination */
91 unsigned char szProductCode[TAPI_MISC_PRODUCT_CODE_LEN_MAX]; /**< product code, null termination */
92 unsigned char szModelId[TAPI_MISC_MODEL_ID_LEN_MAX]; /**< model id (only for CDMA), null termination */
93 unsigned char prl_nam_num; /**< number of PRL NAM fields */
94 unsigned char szPrlVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3]; /**< prl version (only for CDMA), null termination */
95 unsigned char eri_nam_num; /**< number of PRL NAM fields */
96 unsigned char szEriVersion[TAPI_MISC_PRL_ERI_VER_LEN_MAX * 3]; /**< eri version (only for CDMA), null termination */
97 } TelMiscVersionInformation;
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);
101 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data); // from Kernel
102 void on_response_bootup_subscription(TcorePending *p, int data_len, const void *data, void *user_data);
103 void on_response_last_bootup_subscription(TcorePending *p, int data_len, const void *data, void *user_data);
104 static void on_timeout_modem_poweron(TcorePending *p, void *user_data);
105 static void on_response_enable_proactive_command(TcorePending *p, int data_len, const void *data, void *user_data);
107 static void on_timeout_modem_poweron(TcorePending *p, void *user_data)
109 unsigned int data_len = 0;
110 char data[] = "AT+CPAS";
112 dbg("TIMEOUT for 1st AT Command !!!!! NO Response for initial AT command. Resending it");
113 data_len = sizeof(data);
115 /* Retransmit 1st AT command directly via HAL, don't disturb pending queue. */
116 /* HAL was passed as user_data, re-use it */
118 tcore_hal_send_data(user_data, data_len, (void *) data);
122 static void on_confirmation_modem_message_send(TcorePending *p, gboolean result, void *user_data)
124 dbg("on_confirmation_modem_message_send - msg out from queue.\n");
126 if (result == FALSE) {
134 static void on_response_enable_proactive_command(TcorePending *p, int data_len, const void *data, void *user_data)
136 const TcoreATResponse *resp = data;
138 if (resp->success > 0) {
139 dbg("RESPONSE OK proactive command enabled");
141 dbg("RESPONSE NOK proactive command disabled");
145 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)
147 TcoreATRequest *req = NULL;
148 TcoreHal *hal = NULL;
149 CoreObject *o = NULL;
150 TcorePending *pending = NULL;
153 o = tcore_plugin_ref_core_object(plugin, co_name);
154 hal = tcore_object_get_hal(o);
157 pending = tcore_pending_new(o, 0);
159 dbg("Pending is NULL");
160 req = tcore_at_request_new(at_cmd, prefix, at_cmd_type);
162 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
164 tcore_pending_set_request_data(pending, 0, req);
165 tcore_pending_set_response_callback(pending, callback, NULL);
166 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
167 tcore_pending_link_user_request(pending, NULL); // set user request to NULL - this is internal request
168 ret = tcore_hal_send_request(hal, pending);
172 void on_response_bootup_subscription(TcorePending *p, int data_len, const void *data, void *user_data)
174 const TcoreATResponse *resp = data;
176 dbg("entry of on_response_bootup_subscription() - response comes\n");
185 void on_response_last_bootup_subscription(TcorePending *p, int data_len, const void *data, void *user_data)
187 const TcoreATResponse *resp = data;
189 dbg("entry of on_response_last_bootup_subscription() - final response comes\n");
195 dbg("Boot-up configuration completed for IMC modem. Bring CP to online based on Flightmode status\n");
196 on_event_modem_power(NULL, NULL, tcore_pending_ref_plugin(p));
199 static void on_response_power_off(TcorePending *p, int data_len, const void *data, void *user_data)
204 o = tcore_pending_ref_core_object(p);
205 h = tcore_object_get_hal(o);
207 dbg("modem power off");
209 tcore_hal_set_power_state(h, FALSE);
212 static void on_response_set_flight_mode(TcorePending *p, int data_len, const void *data, void *user_data)
214 CoreObject *o = NULL;
215 UserRequest *ur = NULL;
216 const TcoreATResponse *ATresp = data;
217 GSList *tokens = NULL;
218 const char *line = NULL;
219 struct tresp_modem_set_flightmode res = {0};
221 struct tnoti_modem_flight_mode modem_flight_mode = {0};
222 const struct treq_modem_set_flightmode *req_data = NULL;
224 o = tcore_pending_ref_core_object(p);
226 if (ATresp->success > 0) {
227 dbg("RESPONSE OK - flight mode operation finished");
228 res.result = TCORE_RETURN_SUCCESS;
231 line = (const char *) ATresp->final_response;
232 tokens = tcore_at_tok_new(line);
234 if (g_slist_length(tokens) < 1) {
235 dbg("err cause not specified or string corrupted");
236 res.result = TCORE_RETURN_3GPP_ERROR;
238 response = atoi(g_slist_nth_data(tokens, 0));
239 /* TODO: CMEE error mapping is required. */
240 res.result = TCORE_RETURN_3GPP_ERROR;
244 ur = tcore_pending_ref_user_request(p);
246 dbg("No user request. Internal request created during boot-up sequence");
248 if (ATresp->success > 0) {
249 modem_flight_mode.enable = tcore_modem_get_flight_mode_state(o);
250 dbg("sucess case - Sending Flight Mode Notification (%d) to Telephony Server", modem_flight_mode.enable);
252 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_FLIGHT_MODE,
253 sizeof(struct tnoti_modem_flight_mode), &modem_flight_mode);
256 dbg("Sending response for Flight mode operation");
258 req_data = tcore_user_request_ref_data(ur, NULL);
260 if (TCORE_RETURN_SUCCESS == res.result) {
261 if (TRUE == req_data->enable)
269 tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE, sizeof(struct tresp_modem_set_flightmode), &res);
271 if (req_data->enable == 0) {
272 dbg("Flight mode is disabled, trigger COPS to register on network");
273 /* Trigger Network registration (for the moment automatic) */
274 prepare_and_send_pending_request(tcore_object_ref_plugin(o), "modem", "AT+COPS=0", NULL, TCORE_AT_NO_RESULT, NULL);
278 tcore_at_tok_free(tokens);
281 static void on_response_imei(TcorePending *p, int data_len, const void *data, void *user_data)
283 const TcoreATResponse *resp = data;
284 TcorePlugin *plugin = NULL;
285 struct tresp_modem_get_imei res;
286 TelMiscSNInformation *imei_property = NULL;
287 UserRequest *ur = NULL;
288 GSList *tokens = NULL;
292 memset(&res, 0, sizeof(struct tresp_modem_get_imei));
294 if (resp->success > 0) {
297 line = (const char *) resp->lines->data;
298 tokens = tcore_at_tok_new(line);
299 if (g_slist_length(tokens) != 1) {
300 msg("invalid message");
304 res.result = TCORE_RETURN_SUCCESS;
305 strncpy(res.imei, g_slist_nth_data(tokens, 0), 16);
307 dbg("imei = [%s]", res.imei);
309 plugin = tcore_pending_ref_plugin(p);
310 imei_property = tcore_plugin_ref_property(plugin, "IMEI");
312 imei_property->sn_index = TAPI_MISC_ME_IMEI;
313 imei_property->sn_len = strlen(res.imei);
314 memcpy(imei_property->szNumber, res.imei, imei_property->sn_len);
319 line = (const char *) resp->lines->data;
320 tokens = tcore_at_tok_new(line);
324 if (g_slist_length(tokens) < 1) {
325 dbg("err cause not specified or string corrupted");
326 res.result = TCORE_RETURN_3GPP_ERROR;
328 response = atoi(g_slist_nth_data(tokens, 0));
329 /* TODO: CMEE error mapping is required. */
330 res.result = TCORE_RETURN_3GPP_ERROR;
334 ur = tcore_pending_ref_user_request(p);
335 tcore_user_request_send_response(ur, TRESP_MODEM_GET_IMEI, sizeof(struct tresp_modem_get_imei), &res);
339 tcore_at_tok_free(tokens);
344 static void on_response_version(TcorePending *p, int data_len, const void *data, void *user_data)
346 const TcoreATResponse *resp = data;
347 TcorePlugin *plugin = NULL;
348 struct tresp_modem_get_version res = {0};
349 TelMiscVersionInformation *vi_property = NULL;
350 TelMiscVersionInformation *vi = NULL;
351 UserRequest *ur = NULL;
352 GSList *tokens = NULL;
353 const char *line = NULL;
356 char *caldate = NULL;
362 if (resp->success > 0) {
365 line = (const char *) resp->lines->data;
366 tokens = tcore_at_tok_new(line);
367 if (g_slist_length(tokens) == 1) {
368 swver = g_slist_nth_data(tokens, 0);
369 dbg("version: sw=[%s]", swver);
370 } else if (g_slist_length(tokens) == 5) {
371 swver = g_slist_nth_data(tokens, 0);
372 hwver = g_slist_nth_data(tokens, 1);
373 caldate = g_slist_nth_data(tokens, 2);
374 pcode = g_slist_nth_data(tokens, 3);
375 id = g_slist_nth_data(tokens, 4);
377 dbg("version: sw=[%s], hw=[%s], rf_cal=[%s], product_code=[%s], model_id=[%s]", swver, hwver, caldate, pcode, id);
379 msg("invalid message");
384 vi = calloc(sizeof(TelMiscVersionInformation), 1);
386 memcpy(vi->szSwVersion, swver, strlen(swver));
388 memcpy(vi->szHwVersion, hwver, strlen(hwver));
390 memcpy(vi->szRfCalDate, caldate, strlen(caldate));
392 memcpy(vi->szProductCode, pcode, strlen(pcode));
394 memcpy(vi->szModelId, id, strlen(id));
396 memset(&res, 0, sizeof(struct tresp_modem_get_version));
399 snprintf(res.software, (AT_VER_LEN > strlen(swver) ? strlen(swver) : AT_VER_LEN), "%s", swver);
401 snprintf(res.hardware, (AT_VER_LEN > strlen(hwver) ? strlen(hwver) : AT_VER_LEN), "%s", hwver);
403 plugin = tcore_pending_ref_plugin(p);
404 vi_property = tcore_plugin_ref_property(plugin, "VERSION");
405 memcpy(vi_property, vi, sizeof(TelMiscVersionInformation));
410 line = (const char *) resp->lines->data;
411 tokens = tcore_at_tok_new(line);
414 memset(&res, 0, sizeof(struct tresp_modem_get_version));
417 if (g_slist_length(tokens) < 1) {
418 dbg("err cause not specified or string corrupted");
419 res.result = TCORE_RETURN_3GPP_ERROR;
421 response = atoi(g_slist_nth_data(tokens, 0));
422 /* TODO: CMEE error mapping is required. */
423 res.result = TCORE_RETURN_3GPP_ERROR;
427 ur = tcore_pending_ref_user_request(p);
428 tcore_user_request_send_response(ur, TRESP_MODEM_GET_VERSION, sizeof(struct tresp_modem_get_version), &res);
432 tcore_at_tok_free(tokens);
437 static gboolean on_event_bootup_sim_status(CoreObject *o, const void *event_info, void *user_data)
440 GSList *lines = NULL;
444 lines = (GSList *) event_info;
445 if (1 != g_slist_length(lines)) {
446 dbg("unsolicited msg but multiple line");
449 line = (char *) (lines->data);
450 dbg("on_bootup_event_sim_status notification : %s", line);
452 tok = tcore_at_tok_new(line);
453 value = atoi(g_slist_nth_data(tok, 0));
456 dbg("SIM ready. request COPS & remove callback");
457 dbg("power on done set for proactive command receiving mode");
458 prepare_and_send_pending_request(tcore_object_ref_plugin(o), "sat", "AT+CFUN=6", NULL, TCORE_AT_NO_RESULT, on_response_enable_proactive_command);
459 prepare_and_send_pending_request(tcore_object_ref_plugin(o), "umts_network", "AT+COPS=0", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
465 tcore_at_tok_free(tok);
472 gboolean on_event_modem_power(TcoreAT *at, const char *line, TcorePlugin *p)
474 CoreObject *o = NULL;
475 struct treq_modem_set_flightmode flight_mode_set = {0};
476 struct tnoti_modem_power modem_power = {0};
478 Storage *strg = NULL;
480 o = tcore_plugin_ref_core_object(p, "modem");
482 strg = tcore_server_find_storage(tcore_plugin_ref_server(p), "vconf");
483 flight_mode_set.enable = tcore_storage_get_bool(strg, STORAGE_KEY_FLIGHT_MODE_BOOL);
485 h = tcore_object_get_hal(o);
486 tcore_hal_set_power_state(h, TRUE);
488 /* Set Flight mode as per AP settings */
489 if (flight_mode_set.enable) { /* Radio Off */
490 prepare_and_send_pending_request(p, "modem", "AT+CFUN=4", NULL, TCORE_AT_NO_RESULT, on_response_set_flight_mode);
491 tcore_modem_set_flight_mode_state(o, TRUE);
492 } else { /* Radio On */
493 prepare_and_send_pending_request(p, "modem", "AT+CFUN=1", NULL, TCORE_AT_NO_RESULT, on_response_set_flight_mode);
494 tcore_modem_set_flight_mode_state(o, FALSE);
498 prepare_and_send_pending_request(p, "modem", "AT+CGSN", NULL, TCORE_AT_NUMERIC, on_response_imei);
500 /* Get Version Number */
501 prepare_and_send_pending_request(p, "modem", "AT+CGMR", NULL, TCORE_AT_SINGLELINE, on_response_version);
503 tcore_modem_set_powered(o, TRUE);
505 modem_power.state = MODEM_STATE_ONLINE;
507 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_MODEM_POWER,
508 sizeof(struct tnoti_modem_power), &modem_power);
513 static void _modem_subscribe_events(TcorePlugin *plugin)
517 /* XCALLSTAT subscription */
518 prepare_and_send_pending_request(plugin, "call", "at+xcallstat=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
520 /* XSIMSTATE subscription */
521 prepare_and_send_pending_request(plugin, "sim", "at+xsimstate=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
523 prepare_and_send_pending_request(plugin, "umts_sms", "at+xsimstate=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
524 prepare_and_send_pending_request(plugin, "modem", "at+xsimstate=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
526 /* CREG subscription */
527 prepare_and_send_pending_request(plugin, "umts_network", "at+creg=2", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
529 /* CGREG subscription */
530 prepare_and_send_pending_request(plugin, "umts_network", "at+cgreg=2", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
532 /* Allow automatic time Zone updation via NITZ */
533 prepare_and_send_pending_request(plugin, "umts_network", "at+ctzu=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
535 /* TZ, time & daylight changing event reporting subscription */
536 prepare_and_send_pending_request(plugin, "umts_network", "at+ctzr=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
538 /* XMER subscription */
539 prepare_and_send_pending_request(plugin, "umts_network", "at+xmer=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
541 /* CGEREP subscription */
542 prepare_and_send_pending_request(plugin, "umts_ps", "at+cgerep=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
544 /* XDATASTAT subscription */
545 prepare_and_send_pending_request(plugin, "umts_ps", "at+xdatastat=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
547 /* CSSN subscription */
548 prepare_and_send_pending_request(plugin, "call", "at+cssn=1,1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
550 /* CUSD subscription */
551 prepare_and_send_pending_request(plugin, "call", "at+cusd=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
553 /* XDNS subscription */
554 prepare_and_send_pending_request(plugin, "umts_ps", "at+xdns=1,1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
556 /* CLIP subscription */
557 prepare_and_send_pending_request(plugin, "call", "at+clip=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
559 /*CMEE subscription for ps*/
560 prepare_and_send_pending_request(plugin, "umts_ps", "at+cmee=2", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
562 /*CMEE subscription for sms*/
563 prepare_and_send_pending_request(plugin, "umts_sms", "at+cmee=2", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
565 /*incoming sms,cb,status report subscription*/
566 prepare_and_send_pending_request(plugin, "umts_sms", "at+cnmi=1,2,2,1,0", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
568 /* XBCSTAT subscription */
569 prepare_and_send_pending_request(plugin, "sap", "at+xbcstat=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
570 /* AGPS- assist data and reset assist data subscription */
571 prepare_and_send_pending_request(plugin, "gps", "at+cposr=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
573 prepare_and_send_pending_request(plugin, "gps", "at+xcposr=1", NULL, TCORE_AT_NO_RESULT, on_response_bootup_subscription);
575 /* text/pdu mode subscription*/
576 prepare_and_send_pending_request(plugin, "umts_sms", "at+cmgf=0", NULL, TCORE_AT_NO_RESULT, on_response_last_bootup_subscription);
583 static void on_response_setupmux(TcorePending *p, int data_len, const void *data, void *user_data)
585 TcorePlugin *plugin = NULL;
586 TcoreHal *hal = NULL;
591 /* IMC Plugin dereferenced from pending request */
592 plugin = tcore_pending_ref_plugin(p);
594 /* Actual HAL - like svnet(2) */
595 hal = (TcoreHal *) user_data;
597 /* Initialize CMUX */
598 ret = tcore_cmux_init(plugin, hal);
599 if (TCORE_RETURN_SUCCESS == ret) {
600 dbg("Successfully initialized CMUX");
602 err("Failed to initialize CMUX");
611 static void setup_mux(CoreObject *o)
613 TcoreHal *hal = NULL;
614 TcorePending *pending = NULL;
618 /* HAL has type itself,
619 * e.g.) TCORE_HAL_MODE_AT
621 hal = tcore_object_get_hal(o);
623 pending = tcore_at_pending_new(o, "AT+CMUX=0,0,,1509,10,3,30,,", "+CMUX", TCORE_AT_NO_RESULT, on_response_setupmux, hal);
625 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
628 tcore_hal_send_request(hal, pending);
635 static gboolean on_event_mux_channel_up(CoreObject *o, const void *event_info, void *user_data)
637 TcorePlugin *plugin = NULL;
641 plugin = (TcorePlugin *) user_data;
642 _modem_subscribe_events(plugin);
648 static void on_response_enable_logging(TcorePending *p, int data_len, const void *data, void *user_data)
650 const TcoreATResponse *resp = data;
651 TcorePlugin *plugin = NULL;
653 plugin = tcore_pending_ref_plugin(p);
655 /* DELETE ME: only for DEBUG */
659 dbg("response...(result = %d, final_response = '%s')", resp->success, resp->final_response);
663 dbg("Enabling CP logging is success !!!\n");
666 dbg("Enabling CP logging is failed !!!\n");
669 dbg("Calling setup_mux");
670 setup_mux(tcore_pending_ref_core_object(p));
677 static void _send_enable_logging_command(CoreObject *o)
679 TcoreATRequest *req = NULL;
680 TcoreHal *hal = NULL;
681 TcorePending *pending = NULL;
685 dbg("Send Trace enabling command for CP logging. \n");
688 dbg("Co-object is Null !!\n");
692 hal = tcore_object_get_hal(o);
693 pending = tcore_pending_new(o, 0);
694 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);
696 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
698 tcore_pending_set_request_data(pending, 0, req);
699 tcore_pending_set_response_callback(pending, on_response_enable_logging, hal);
700 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
702 ret = tcore_hal_send_request(hal, pending);
703 if (ret != TCORE_RETURN_SUCCESS)
704 dbg("tcore_hal_send_request fail !!! (hal: 0x%x, pending: 0x%x)\n", hal, pending);
707 static void on_response_poweron(TcorePending *p, int data_len, const void *data, void *user_data)
709 const TcoreATResponse *resp = data;
710 GSList *tokens = NULL;
711 const char *line = NULL;
712 gboolean bpoweron = FALSE;
717 /* Parse AT Response */
719 line = (const char *) resp->lines->data;
720 tokens = tcore_at_tok_new(line);
721 if (g_slist_length(tokens) != 1) {
722 dbg("invalid message");
728 response = atoi(g_slist_nth_data(tokens, 0));
730 dbg("CPAS: response %d", response);
734 case CPAS_RES_RINGING:
735 case CPAS_RES_CALL_PROGRESS:
736 case CPAS_RES_ASLEEP:
740 case CPAS_RES_UNAVAIL:
741 case CPAS_RES_UNKNOWN:
743 dbg("value is unvail/unknown - but CP responded - proceed poweron");
749 dbg("CPAS: RESPONSE NOK");
754 /* DELE ME: AT request & response are freed after AT processing in HAL.
755 * ref.) _emit_pending_response (libtcore/src/at.c)
758 tcore_at_tok_free(tokens);
760 if (bpoweron == TRUE) {
761 dbg("Power on NOTI received, (pending: 0x%x, co: 0x%x)\n", p, tcore_pending_ref_core_object(p));
763 _send_enable_logging_command(tcore_pending_ref_core_object(p));
765 dbg("CP is not ready, let us send CPAS once again");
766 s_modem_send_poweron(tcore_object_ref_plugin(tcore_pending_ref_core_object(p)));
771 static TReturn power_off(CoreObject *o, UserRequest *ur)
773 TcoreHal *hal = NULL;
774 TcoreATRequest *req = NULL;
775 TcorePending *pending = NULL;
777 hal = tcore_object_get_hal(o);
778 pending = tcore_pending_new(o, 0);
780 req = tcore_at_request_new("AT+CFUN=0", NULL, TCORE_AT_NO_RESULT);
782 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
784 tcore_pending_set_request_data(pending, 0, req);
785 tcore_pending_set_response_callback(pending, on_response_power_off, hal);
786 tcore_pending_link_user_request(pending, ur);
787 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
789 tcore_hal_send_request(hal, pending);
791 return TCORE_RETURN_SUCCESS;
794 static TReturn get_imei(CoreObject *o, UserRequest *ur)
798 TcorePending *pending = NULL;
800 hal = tcore_object_get_hal(o);
801 if (FALSE == tcore_hal_get_power_state(hal)) {
802 dbg("cp not ready/n");
803 return TCORE_RETURN_ENOSYS;
805 pending = tcore_pending_new(o, 0);
807 req = tcore_at_request_new("AT+CGSN", NULL, TCORE_AT_NUMERIC);
809 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
811 tcore_pending_set_request_data(pending, 0, req);
812 tcore_pending_set_response_callback(pending, on_response_imei, hal);
813 tcore_pending_link_user_request(pending, ur);
814 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
816 tcore_hal_send_request(hal, pending);
818 return TCORE_RETURN_SUCCESS;
822 static TReturn get_version(CoreObject *o, UserRequest *ur)
826 TcorePending *pending = NULL;
828 hal = tcore_object_get_hal(o);
829 if (FALSE == tcore_hal_get_power_state(hal)) {
830 dbg("cp not ready/n");
831 return TCORE_RETURN_ENOSYS;
833 pending = tcore_pending_new(o, 0);
835 req = tcore_at_request_new("AT+CGMR", NULL, TCORE_AT_SINGLELINE);
837 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
839 tcore_pending_set_request_data(pending, 0, req);
840 tcore_pending_set_response_callback(pending, on_response_version, hal);
841 tcore_pending_link_user_request(pending, ur);
842 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
844 tcore_hal_send_request(hal, pending);
846 return TCORE_RETURN_SUCCESS;
849 static TReturn set_flight_mode(CoreObject *o, UserRequest *ur)
851 TcoreHal *hal = NULL;
852 TcoreATRequest *req = NULL;
853 TcorePending *pending = NULL;
854 const struct treq_modem_set_flightmode *req_data = NULL;
855 char *cmd_str = NULL;
857 hal = tcore_object_get_hal(o);
858 if (FALSE == tcore_hal_get_power_state(hal)) {
859 dbg("cp not ready/n");
860 return TCORE_RETURN_ENOSYS;
862 pending = tcore_pending_new(o, 0);
864 req_data = tcore_user_request_ref_data(ur, NULL);
866 if (req_data->enable) {
867 dbg("Flight mode on/n");
868 cmd_str = g_strdup("AT+CFUN=4");
870 dbg("Flight mode off/n");
871 cmd_str = g_strdup("AT+CFUN=1");
874 req = tcore_at_request_new((const char *) cmd_str, NULL, TCORE_AT_NO_RESULT);
876 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
878 tcore_pending_set_request_data(pending, 0, req);
879 tcore_pending_set_response_callback(pending, on_response_set_flight_mode, hal);
880 tcore_pending_link_user_request(pending, ur);
881 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
883 tcore_hal_send_request(hal, pending);
885 return TCORE_RETURN_SUCCESS;
889 static struct tcore_modem_operations modem_ops = {
891 .power_off = power_off,
893 .set_flight_mode = set_flight_mode,
894 .get_imei = get_imei,
895 .get_version = get_version,
897 .dun_pin_ctrl = NULL,
900 gboolean s_modem_init(TcorePlugin *p, TcoreHal *h)
902 CoreObject *o = NULL;
903 GQueue *work_queue = NULL;
904 TelMiscVersionInformation *vi_property = NULL;
905 TelMiscSNInformation *imei_property = NULL;
906 TelMiscSNInformation *sn_property = NULL;
908 o = tcore_modem_new(p, "modem", &modem_ops, h);
912 work_queue = g_queue_new();
913 tcore_object_link_user_data(o, work_queue);
915 vi_property = calloc(sizeof(TelMiscVersionInformation), 1);
916 tcore_plugin_link_property(p, "VERSION", vi_property);
918 imei_property = calloc(sizeof(TelMiscSNInformation), 1);
919 tcore_plugin_link_property(p, "IMEI", imei_property);
921 sn_property = calloc(sizeof(TelMiscSNInformation), 1);
922 tcore_plugin_link_property(p, "SN", sn_property);
924 dbg("Registerind for CMUX-UP event");
925 tcore_object_add_callback(o, "CMUX-UP", on_event_mux_channel_up, p);
927 dbg("Registering for +XSIM event");
928 tcore_object_add_callback(o, "+XSIM", on_event_bootup_sim_status, NULL);
933 void s_modem_exit(TcorePlugin *p)
935 CoreObject *o = NULL;
936 GQueue *work_queue = NULL;
937 TelMiscVersionInformation *vi_property = NULL;
938 TelMiscSNInformation *imei_property = NULL;
939 TelMiscSNInformation *sn_property = NULL;
944 o = tcore_plugin_ref_core_object(p, "modem");
946 work_queue = tcore_object_ref_user_data(o);
947 g_queue_free(work_queue);
949 vi_property = tcore_plugin_ref_property(p, "VERSION");
953 imei_property = tcore_plugin_ref_property(p, "IMEI");
957 sn_property = tcore_plugin_ref_property(p, "SN");
965 gboolean s_modem_send_poweron(TcorePlugin *p)
969 TcorePending *pending = NULL;
972 o = tcore_plugin_ref_core_object(p, "modem");
973 hal = tcore_object_get_hal(o);
975 pending = tcore_pending_new(o, 0);
977 req = tcore_at_request_new("AT+CPAS", "+CPAS", TCORE_AT_SINGLELINE);
979 dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd));
981 tcore_pending_set_timeout(pending, 10);
982 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
983 tcore_pending_set_timeout_callback(pending, on_timeout_modem_poweron, hal);
985 tcore_pending_set_request_data(pending, 0, req);
986 tcore_pending_set_response_callback(pending, on_response_poweron, hal);
987 tcore_pending_set_send_callback(pending, on_confirmation_modem_message_send, NULL);
989 tcore_hal_send_request(hal, pending);