2 * tel-plugin-packetservice
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: DongHoo Park <donghoo.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.
22 #include "ps_common.h"
24 #include "ps_context.h"
26 #include "ps_service.h"
31 #include <co_context.h>
34 #include <type/network.h>
35 #include <co_network.h>
37 #include <user_request.h>
41 #ifdef TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL
44 ON_NON_CALL_NOTI_HOOK,
46 } __ps_call_flow_type;
48 static gboolean __ps_set_network_mode(int mode, void *data)
51 gboolean roaming = FALSE;
52 struct treq_network_set_mode req;
54 UserRequest *ur = NULL;
55 ps_modem_t *modem = data;
57 CoreObject *co_network = NULL;
59 memset(&req, 0, sizeof(struct treq_network_set_mode));
61 co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(modem->co_modem),
62 CORE_OBJECT_TYPE_NETWORK);
65 if (modem->data_allowed)
66 c_mode |= NETWORK_MODE_LTE;
68 c_mode &= ~NETWORK_MODE_LTE;
70 roaming = tcore_network_get_roaming_state(co_network);
71 if (modem->data_allowed && roaming)
72 c_mode &= ~NETWORK_MODE_LTE;
74 ps_dbg_ex_modem(modem, "candidate mode(%d), current mode(%d), roaming(%d), data allowed(%d)", c_mode, mode, roaming, modem->data_allowed);
80 ur = tcore_user_request_new(NULL, tcore_plugin_ref_plugin_name(tcore_object_ref_plugin(co_network)));
81 tcore_user_request_set_data(ur, sizeof(struct treq_network_set_mode), &req);
82 tcore_user_request_set_command(ur, TREQ_NETWORK_SET_MODE);
84 if (TCORE_RETURN_SUCCESS != tcore_server_dispatch_request(tcore_plugin_ref_server(tcore_object_ref_plugin(modem->co_modem)), ur)) {
85 ps_err_ex_modem(modem, "Failed to dispatch");
86 tcore_user_request_unref(ur);
92 /* Function will be used in case any dispatch request failed in ps plugin */
93 static void __ps_send_ur_dispatch_failure_response(UserRequest *ur, enum tcore_response_command command)
95 err("User request dispatch failed so need to send response for command [%d]", command);
97 case TRESP_NETWORK_SEARCH: {
98 struct tresp_network_search search_rsp;
99 memset(&search_rsp, 0, sizeof(struct tresp_network_search));
101 search_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
102 search_rsp.list_count = 0;
103 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH,
104 sizeof(struct tresp_network_search), &search_rsp);
108 case TRESP_NETWORK_SET_PLMN_SELECTION_MODE: {
109 struct tresp_network_set_plmn_selection_mode set_plmn_selection_mode_rsp;
110 memset(&set_plmn_selection_mode_rsp, 0, sizeof(struct tresp_network_set_plmn_selection_mode));
112 set_plmn_selection_mode_rsp.result = TCORE_RETURN_FAILURE;
113 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
114 sizeof(struct tresp_network_set_plmn_selection_mode), &set_plmn_selection_mode_rsp);
118 case TRESP_NETWORK_SET_MODE: {
119 struct tresp_network_set_mode set_rsp;
120 memset(&set_rsp, 0, sizeof(struct tresp_network_set_mode));
122 set_rsp.result = TCORE_RETURN_FAILURE;
123 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_MODE,
124 sizeof(struct tresp_network_set_mode), &set_rsp);
128 case TRESP_NETWORK_GET_MODE: {
129 struct tresp_network_get_mode get_rsp;
130 memset(&get_rsp, 0, sizeof(struct tresp_network_get_mode));
132 get_rsp.result = TCORE_RETURN_FAILURE;
133 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_MODE,
134 sizeof(struct tresp_network_get_mode), &get_rsp);
138 case TRESP_MODEM_POWER_OFF: {
139 struct tresp_modem_power_off set_power_off_rsp;
140 memset(&set_power_off_rsp, 0, sizeof(struct tresp_modem_power_off));
142 set_power_off_rsp.result = TCORE_RETURN_FAILURE;
143 tcore_user_request_send_response(ur, TRESP_MODEM_POWER_OFF,
144 sizeof(struct tresp_modem_power_off), &set_power_off_rsp);
148 case TRESP_MODEM_POWER_LOW: {
149 struct tresp_modem_power_low set_power_low_rsp;
150 memset(&set_power_low_rsp, 0, sizeof(struct tresp_modem_power_low));
152 set_power_low_rsp.result = TCORE_RETURN_FAILURE;
153 tcore_user_request_send_response(ur, TRESP_MODEM_POWER_LOW,
154 sizeof(struct tresp_modem_power_low), &set_power_low_rsp);
158 case TRESP_MODEM_SET_FLIGHTMODE: {
159 struct tresp_modem_set_flightmode set_flight_mode_rsp;
160 memset(&set_flight_mode_rsp, 0, sizeof(struct tresp_modem_set_flightmode));
162 set_flight_mode_rsp.result = TCORE_RETURN_FAILURE;
163 tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE,
164 sizeof(struct tresp_modem_set_flightmode), &set_flight_mode_rsp);
169 err("Command type not expected [%d]", command);
171 /* Unref User request */
172 tcore_user_request_unref(ur);
175 static void __ps_hook_response_cb(UserRequest *ur, enum tcore_response_command command,
176 unsigned int data_len, const void *data, void *user_data)
178 ps_modem_t *modem = user_data;
179 CoreObject *co_modem = _ps_modem_ref_co_modem(modem);
182 id = ((command & ~TCORE_RESPONSE) & TCORE_REQUEST);
184 ps_dbg_ex_modem(modem, "Entered");
185 count = ps_util_get_waiting_job_count(modem->work_queue, id);
188 ur = ps_util_pop_waiting_job(modem->work_queue, id);
190 CoreObject *co_network = NULL;
191 TReturn ret = TCORE_RETURN_SUCCESS;
193 co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_modem),
194 CORE_OBJECT_TYPE_NETWORK);
196 ps_info_ex_modem(modem, "Sending Pending Request of type = id", id);
197 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
198 if ((command == TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH)
199 || (command == TRESP_NETWORK_SEARCH)
200 || (command == TRESP_NETWORK_SET_PLMN_SELECTION_MODE)
201 || (command == TRESP_NETWORK_SET_MODE)
202 || (command == TRESP_NETWORK_GET_MODE))
203 ret = tcore_object_dispatch_request(co_network, ur);
204 else if ((command == TRESP_MODEM_SET_FLIGHTMODE)
205 || (command == TRESP_MODEM_POWER_LOW)
206 || (command == TRESP_MODEM_POWER_OFF))
207 ret = tcore_object_dispatch_request(co_modem, ur);
208 if (TCORE_RETURN_SUCCESS != ret) {
209 /* send responce wrt to command */
210 __ps_send_ur_dispatch_failure_response(ur, command);
217 case TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH:
218 case TRESP_NETWORK_SEARCH:
219 ps_dbg_ex_modem(modem, "TRESP_NETWORK_SEARCH response received");
221 modem->hook_flag &= PS_RESET_NETWORK_SEARCH_FLAG;
224 case TRESP_NETWORK_SET_PLMN_SELECTION_MODE:
225 ps_dbg_ex_modem(modem, "TRESP_NETWORK_SET_PLMN_SELECTION_MODE response received ");
227 modem->hook_flag &= PS_NETWORK_RESET_SELECTION_FLAG;
230 case TRESP_NETWORK_SET_MODE: {
231 ps_dbg_ex_modem(modem, "TRESP_NETWORK_SET_MODE response received ");
234 modem->hook_flag &= PS_NETWORK_RESET_SELECT_MODE_FLAG;
235 modem->mode_pref_changed = FALSE;
237 ps_dbg_ex_modem(modem, "mode_pref_changed : %d", modem->mode_pref_changed);
241 case TRESP_NETWORK_GET_MODE: {
243 const struct tresp_network_get_mode *resp_get_mode = data;
244 ps_dbg_ex_modem(modem, "TRESP_NETWORK_GET_MODE response received mode (mode:[%d])", resp_get_mode->mode);
247 modem->hook_flag &= PS_NETWORK_RESET_GET_MODE_FLAG;
249 rv = __ps_set_network_mode(resp_get_mode->mode, modem);
251 ps_dbg_ex_modem(modem, "network set mode request!");
257 case TRESP_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION:
258 ps_dbg_ex_modem(modem, "TRESP_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION response received ");
260 modem->hook_flag &= PS_NETWORK_RESET_SET_DEFAULT_DATA_SUBS;
263 case TRESP_MODEM_SET_FLIGHTMODE: {
265 gpointer key, service;
266 ps_context_t *def_context = NULL, *ims_context = NULL;
268 ps_dbg_ex_modem(modem, "TRESP_MODEM_SET_FLIGHTMODE response received ");
270 modem->hook_flag &= PS_NETWORK_RESET_SET_FLIGHT_MODE_FLAG;
272 g_hash_table_iter_init(&iter, modem->services);
273 while (g_hash_table_iter_next(&iter, &key, &service) == TRUE) {
274 def_context = _ps_service_return_default_context(service, CONTEXT_ROLE_INTERNET);
276 _ps_context_set_alwayson_enable(def_context, TRUE);
278 ims_context = _ps_service_return_default_context(service, CONTEXT_ROLE_IMS);
280 _ps_context_set_alwayson_enable(ims_context, TRUE);
286 case TRESP_MODEM_POWER_LOW:
287 ps_dbg_ex_modem(modem, "TRESP_MODEM_POWER_LOW response received ");
289 modem->hook_flag &= PS_NETWORK_RESET_SET_POWER_LOW_FLAG;
292 case TRESP_MODEM_POWER_OFF:
293 ps_dbg_ex_modem(modem, "TRESP_MODEM_POWER_OFF response received ");
295 modem->hook_flag &= PS_NETWORK_RESET_SET_POWER_OFF_FLAG;
298 case TRESP_SIM_SET_POWERSTATE:
299 ps_dbg_ex_modem(modem, "TRESP_SIM_SET_POWERSTATE response received ");
301 modem->hook_flag &= PS_SIM_SET_POWER_STATE_FLAG;
305 ps_warn_ex_modem(modem, "Unexpected response ");
310 ps_info_ex_modem(modem, "After unset - FLAG %x", modem->hook_flag);
311 if (modem->hook_flag == PS_NO_PENDING_REQUEST
312 && command != TRESP_MODEM_POWER_LOW
313 && command != TRESP_MODEM_POWER_OFF
314 && modem->mode_pref_changed == FALSE) {
315 _ps_modem_connect_default_context(modem);
319 static void __ps_modem_get_mode_pref_change(ps_modem_t *modem, UserRequest *ur)
321 enum telephony_network_service_type svc_type;
322 enum tcore_request_command cmd;
323 CoreObject *co_network = NULL;
324 const struct treq_network_set_mode *req;
326 cmd = tcore_user_request_get_command(ur);
327 if (cmd != TREQ_NETWORK_SET_MODE) {
328 ps_warn_ex_modem(modem, "Not a TREQ_NETWORK_SET_MODE");
329 modem->mode_pref_changed = FALSE;
332 modem->mode_pref_changed = TRUE;
334 co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(modem->co_modem),
335 CORE_OBJECT_TYPE_NETWORK);
336 req = tcore_user_request_ref_data(ur, NULL);
338 tcore_network_get_service_type(co_network, &svc_type);
339 ps_dbg_ex_modem(modem, "mode_pref[0x%x], svc_type[%d]", req->mode, svc_type);
341 case NETWORK_SERVICE_TYPE_2G:
342 case NETWORK_SERVICE_TYPE_2_5G:
343 case NETWORK_SERVICE_TYPE_2_5G_EDGE: {
344 if (req->mode == NETWORK_MODE_GSM)
345 modem->mode_pref_changed = FALSE;
349 case NETWORK_SERVICE_TYPE_3G:
350 case NETWORK_SERVICE_TYPE_HSDPA: {
351 if (req->mode & NETWORK_MODE_WCDMA)
352 modem->mode_pref_changed = FALSE;
356 case NETWORK_SERVICE_TYPE_LTE: {
357 if (req->mode & NETWORK_MODE_LTE)
358 modem->mode_pref_changed = FALSE;
366 ps_dbg_ex_modem(modem, "mode_pref_changed : %d", modem->mode_pref_changed);
369 static int __ps_deactivation_timeout_handler(alarm_id_t alarm_id, void *data)
371 ps_modem_t *modem = data;
374 ps_dbg_ex_modem(modem, "remove connection retry timer (%d)", alarm_id);
375 alarmmgr_remove_alarm(alarm_id);
378 ps_dbg_ex_modem(modem, "Deactivation timeout, proceed pending cmd");
379 /* Handle any pending request if present */
380 _ps_hook_send_pending_user_request(modem);
384 static void __ps_set_deactivation_timeout(ps_modem_t *modem, int timeout)
390 ret = device_power_request_lock(POWER_LOCK_CPU, 0);
392 ps_dbg_ex_modem(modem, "ret : (0x%x)", ret);
394 result = alarmmgr_add_alarm_withcb(ALARM_TYPE_VOLATILE, (time_t)(timeout),
395 0, __ps_deactivation_timeout_handler, modem, &(modem->deact_timer_src));
398 ret = device_power_release_lock(POWER_LOCK_CPU);
400 ps_dbg_ex_modem(modem, "ret : (0x%x)", ret);
402 if (result != ALARMMGR_RESULT_SUCCESS) {
403 ps_dbg_ex_modem(modem, "Failed to add alarm(%d)", result);
407 ps_dbg_ex_modem(modem, "deactivation timeout - timer src(%d), timeout(%d)", modem->deact_timer_src, timeout);
410 static void __ps_modem_set_hook_flag(ps_modem_t *modem, enum tcore_request_command cmd)
413 case TREQ_NETWORK_SEARCH:
414 ps_dbg_ex_modem(modem, "TREQ_NETWORK_SEARCH");
415 modem->hook_flag |= PS_NETWORK_SEARCH_PENDING;
416 ps_dbg_ex_modem(modem, "TREQ_NETWORK_SEARCH setting flag %x", modem->hook_flag);
419 case TREQ_NETWORK_SET_PLMN_SELECTION_MODE:
420 modem->hook_flag |= PS_NETWORK_SELECTION_PENDING;
421 ps_dbg_ex_modem(modem, "TREQ_NETWORK_SET_PLMN_SELECTION_MODE setting flag %x", modem->hook_flag);
424 case TREQ_NETWORK_SET_MODE:
425 modem->hook_flag |= PS_NETWORK_SELECT_MODE;
426 ps_dbg_ex_modem(modem, "TREQ_NETWORK_SET_MODE setting flag %x", modem->hook_flag);
429 case TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION:
430 modem->hook_flag |= PS_NETWORK_SET_DEFAULT_DATA_SUBS;
431 ps_dbg_ex_modem(modem, "TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION setting flag %x", modem->hook_flag);
434 case TREQ_MODEM_SET_FLIGHTMODE:
435 modem->hook_flag |= PS_NETWORK_SET_FLIGHT_MODE;
436 ps_dbg_ex_modem(modem, "TREQ_MODEM_SET_FLIGHTMODE setting flag %x", modem->hook_flag);
439 case TREQ_MODEM_POWER_OFF:
440 modem->hook_flag |= PS_NETWORK_SET_POWER_OFF;
441 ps_dbg_ex_modem(modem, "TREQ_MODEM_POWER_OFF setting flag %x", modem->hook_flag);
444 case TREQ_MODEM_POWER_LOW:
445 modem->hook_flag |= PS_NETWORK_SET_POWER_LOW;
446 ps_dbg_ex_modem(modem, "TREQ_MODEM_POWER_LOW setting flag %x", modem->hook_flag);
449 case TREQ_SIM_SET_POWERSTATE:
450 modem->hook_flag |= PS_SIM_SET_POWER_STATE;
451 ps_dbg_ex_modem(modem, "TREQ_SIM_SET_POWERSTATE setting flag %x", modem->hook_flag);
455 ps_dbg_ex_modem(modem, "Not handled request");
458 ps_info_ex_modem(modem, "After set - FLAG %x", modem->hook_flag);
461 static enum tcore_hook_return __ps_handle_modem_power_on(ps_modem_t *modem, UserRequest *ur)
463 if (modem->powered == PS_MODEM_STATE_ONLINE) {
464 struct tresp_modem_power_on set_power_on;
465 memset(&set_power_on, 0, sizeof(struct tresp_modem_power_on));
466 ps_dbg_ex_modem(modem, "FLAG: 0x%x", modem->hook_flag);
468 if (modem->hook_flag & PS_NETWORK_SET_POWER_LOW) {
469 ps_dbg_ex_modem(modem, "LOW power request is pending, send abort response");
470 set_power_on.result = TCORE_RETURN_OPERATION_ABORTED;
471 tcore_user_request_send_response(ur, TRESP_MODEM_POWER_ON,
472 sizeof(struct tresp_modem_power_on), &set_power_on);
474 ps_dbg_ex_modem(modem, "No pending LOW power request, send success response.");
475 set_power_on.result = TCORE_RETURN_EALREADY;
476 tcore_user_request_send_response(ur, TRESP_MODEM_POWER_ON,
477 sizeof(struct tresp_modem_power_on), &set_power_on);
479 tcore_user_request_unref(ur);
480 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
482 return TCORE_HOOK_RETURN_CONTINUE;
485 static void __ps_handle_waiting_job(UserRequest *ur, enum tcore_request_command cmd)
487 if (cmd == TREQ_NETWORK_SEARCH) {
488 struct tresp_network_search search_rsp;
489 memset(&search_rsp, 0, sizeof(struct tresp_network_search));
491 search_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
492 search_rsp.list_count = 0;
493 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH,
494 sizeof(struct tresp_network_search), &search_rsp);
495 } else if (cmd == TREQ_NETWORK_SET_PLMN_SELECTION_MODE) {
496 struct tresp_network_set_plmn_selection_mode set_plmn_mode_rsp;
497 memset(&set_plmn_mode_rsp, 0, sizeof(struct tresp_network_set_plmn_selection_mode));
499 set_plmn_mode_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
500 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
501 sizeof(struct tresp_network_set_plmn_selection_mode), &set_plmn_mode_rsp);
502 } else if (cmd == TREQ_NETWORK_SET_MODE) {
503 struct tresp_network_set_mode setmode_rsp;
504 memset(&setmode_rsp, 0, sizeof(struct tresp_network_set_mode));
506 setmode_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
507 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_MODE,
508 sizeof(struct tresp_network_set_mode), &setmode_rsp);
509 } else if (cmd == TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH) {
510 struct tresp_network_set_cancel_manual_search search_cancel_rsp;
511 memset(&search_cancel_rsp, 0, sizeof(struct tresp_network_set_cancel_manual_search));
513 search_cancel_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
514 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH,
515 sizeof(struct tresp_network_set_cancel_manual_search), &search_cancel_rsp);
516 } else if (cmd == TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION) {
517 struct tresp_network_set_default_data_subscription default_data_rsp;
518 memset(&default_data_rsp, 0, sizeof(struct tresp_network_set_default_data_subscription));
520 default_data_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
521 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION,
522 sizeof(struct tresp_network_set_default_data_subscription), &default_data_rsp);
523 } else if (cmd == TREQ_MODEM_SET_FLIGHTMODE) {
524 struct tresp_modem_set_flightmode set_flight_mode;
525 memset(&set_flight_mode, 0, sizeof(struct tresp_modem_set_flightmode));
527 set_flight_mode.result = TCORE_RETURN_OPERATION_ABORTED;
528 tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE,
529 sizeof(struct tresp_modem_set_flightmode), &set_flight_mode);
530 } else if (cmd == TREQ_MODEM_POWER_OFF) {
531 struct tresp_modem_power_off set_power_off;
532 memset(&set_power_off, 0, sizeof(struct tresp_modem_power_off));
534 set_power_off.result = TCORE_RETURN_OPERATION_ABORTED;
535 tcore_user_request_send_response(ur, TRESP_MODEM_POWER_OFF,
536 sizeof(struct tresp_modem_power_off), &set_power_off);
537 } else if (cmd == TREQ_MODEM_POWER_LOW) {
538 struct tresp_modem_power_low set_power_low;
539 memset(&set_power_low, 0, sizeof(struct tresp_modem_power_low));
541 set_power_low.result = TCORE_RETURN_OPERATION_ABORTED;
542 tcore_user_request_send_response(ur, TRESP_MODEM_POWER_LOW,
543 sizeof(struct tresp_modem_power_low), &set_power_low);
544 } else if (cmd == TREQ_SIM_SET_POWERSTATE) {
545 struct tresp_sim_set_powerstate set_power;
546 memset(&set_power, 0, sizeof(struct tresp_sim_set_powerstate));
548 set_power.result = TCORE_RETURN_OPERATION_ABORTED;
549 tcore_user_request_send_response(ur, TRESP_SIM_SET_POWERSTATE,
550 sizeof(struct tresp_sim_set_powerstate), &set_power);
552 tcore_user_request_unref(ur);
555 static enum tcore_hook_return __ps_handle_network_search_modem_changed(ps_modem_t *modem, CoreObject *co_ps,
556 UserRequest *ur, enum tcore_request_command cmd)
558 gboolean ret = FALSE;
559 TReturn rv = TCORE_RETURN_FAILURE;
562 gpointer key, service;
566 if (!modem || !co_ps || !ur)
567 return TCORE_HOOK_RETURN_CONTINUE;
569 if (FALSE == tcore_ps_any_context_activating_activated(co_ps, &value)) {
570 ps_dbg_ex_modem(modem, "No activating/activated context present");
571 /* Block PS always-on while network operations. */
572 __ps_modem_set_hook_flag(modem, cmd);
573 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
574 return TCORE_HOOK_RETURN_CONTINUE;
577 ps_info_ex_modem(modem, "Value returned [%d]", value);
578 if (CONTEXT_STATE_ACTIVATED == value) {
579 ps_dbg_ex_modem(modem, "Internet/mms/tethering Activated/Activating context present need to deactivate them");
580 if (cmd == TREQ_NETWORK_SEARCH) {
581 g_hash_table_iter_init(&iter, modem->services);
582 while (g_hash_table_iter_next(&iter, &key, &service) == TRUE)
583 _ps_service_disconnect_internet_mms_tethering_contexts(service);
585 rv = tcore_ps_deactivate_contexts(co_ps);
586 if (rv != TCORE_RETURN_SUCCESS) {
587 ps_dbg_ex_modem(modem, "fail to deactivation");
588 return TCORE_HOOK_RETURN_CONTINUE;
591 } else if (CONTEXT_STATE_ACTIVATING == value) {
592 if (cmd == TREQ_MODEM_SET_FLIGHTMODE) {
593 ps_info_ex_modem(modem, "No need to stop these request for pdp in activating state ");
594 return TCORE_HOOK_RETURN_CONTINUE;
596 ps_dbg_ex_modem(modem, "For rest command will wait for activation successful ");
598 if (!modem->work_queue) {
599 ps_err_ex_modem(modem, "no queue present unable to handle request");
600 return TCORE_HOOK_RETURN_CONTINUE;
603 job_cnt = ps_util_get_waiting_job_count(modem->work_queue, cmd);
605 ps_err_ex_modem(modem, "duplicated job for cmd(%d)", cmd);
607 if (cmd == TREQ_NETWORK_SEARCH) {
608 struct tresp_network_search search_rsp;
609 memset(&search_rsp, 0, sizeof(struct tresp_network_search));
611 search_rsp.result = TCORE_RETURN_OPERATION_ABORTED;
612 search_rsp.list_count = 0;
613 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH,
614 sizeof(struct tresp_network_search), &search_rsp);
615 } else if (cmd == TREQ_MODEM_SET_FLIGHTMODE) {
616 struct tresp_modem_set_flightmode set_flight_mode;
617 memset(&set_flight_mode, 0, sizeof(struct tresp_modem_set_flightmode));
619 set_flight_mode.result = TCORE_RETURN_OPERATION_ABORTED;
620 tcore_user_request_send_response(ur, TRESP_MODEM_SET_FLIGHTMODE,
621 sizeof(struct tresp_modem_set_flightmode), &set_flight_mode);
624 tcore_user_request_unref(ur);
625 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
627 ret = ps_util_add_waiting_job(modem->work_queue, cmd, ur);
629 ps_err_ex_modem(modem, "fail to add the request to queue");
630 return TCORE_HOOK_RETURN_CONTINUE;
633 __ps_modem_get_mode_pref_change(modem, ur);
634 __ps_modem_set_hook_flag(modem, cmd);
635 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
639 static enum tcore_hook_return __ps_handle_cancel_manual_search_modem_changed(ps_modem_t *modem, UserRequest *ur)
641 UserRequest *ur_pending = NULL;
642 ur_pending = ps_util_pop_waiting_job(modem->work_queue, TREQ_NETWORK_SEARCH);
645 ps_dbg_ex_modem(modem, "no pendig search request");
646 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
647 return TCORE_HOOK_RETURN_CONTINUE;
649 struct tresp_network_search search_rsp;
650 struct tresp_network_set_cancel_manual_search search_cancel_rsp;
652 memset(&search_rsp, 0, sizeof(struct tresp_network_search));
653 memset(&search_cancel_rsp, 0, sizeof(struct tresp_network_set_cancel_manual_search));
655 search_rsp.list_count = 0;
656 ps_dbg_ex_modem(modem, "send search response to upper layer");
657 tcore_user_request_send_response(ur_pending, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &search_rsp);
658 tcore_user_request_unref(ur_pending);
660 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
661 search_cancel_rsp.result = TCORE_RETURN_SUCCESS;
662 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH,
663 sizeof(struct tresp_network_set_cancel_manual_search), &search_cancel_rsp);
665 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
667 return TCORE_HOOK_RETURN_CONTINUE;
670 static void __ps_handle_cancel_manual_search(ps_modem_t *modem, UserRequest *ur, UserRequest *ur_pending)
672 struct tresp_network_search search_rsp;
673 struct tresp_network_set_cancel_manual_search search_cancel_rsp;
675 memset(&search_rsp, 0, sizeof(struct tresp_network_search));
676 memset(&search_cancel_rsp, 0, sizeof(struct tresp_network_set_cancel_manual_search));
678 search_rsp.list_count = 0;
679 ps_dbg_ex_modem(modem, "send search response to upper layer");
680 tcore_user_request_send_response(ur_pending, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &search_rsp);
681 tcore_user_request_unref(ur_pending);
683 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
684 search_cancel_rsp.result = TCORE_RETURN_SUCCESS;
685 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH,
686 sizeof(struct tresp_network_set_cancel_manual_search), &search_cancel_rsp);
689 static enum tcore_hook_return ps_handle_hook(Server *s, UserRequest *ur, void *user_data)
691 gboolean ret = FALSE;
692 TReturn rv = TCORE_RETURN_FAILURE;
694 CoreObject *co_ps = NULL;
695 TcorePlugin *target_plg = NULL;
698 ps_modem_t *modem = user_data;
699 CoreObject *co_modem = _ps_modem_ref_co_modem(modem);
701 gpointer key, service;
703 char *modem_name = NULL;
704 enum tcore_request_command cmd = tcore_user_request_get_command(ur);
706 ps_dbg_ex_modem(modem, "Entered");
708 modem_name = tcore_user_request_get_modem_name(ur);
710 return TCORE_HOOK_RETURN_CONTINUE;
712 target_plg = tcore_object_ref_plugin(co_modem);
713 if (g_strcmp0(tcore_server_get_cp_name_by_plugin(target_plg), modem_name) != 0) {
714 ps_info_ex_modem(modem, "request modem (%s) not matched current modem(%s)",
716 tcore_server_get_cp_name_by_plugin(target_plg));
719 if (cmd == TREQ_NETWORK_SEARCH || cmd == TREQ_MODEM_SET_FLIGHTMODE) {
720 co_ps = tcore_plugin_ref_core_object(target_plg, CORE_OBJECT_TYPE_PS);
722 ps_err_ex_modem(modem, "No ps core object present ");
723 return TCORE_HOOK_RETURN_CONTINUE;
725 return __ps_handle_network_search_modem_changed(modem, co_ps, ur, cmd);
726 } else if (cmd == TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH) {
727 return __ps_handle_cancel_manual_search_modem_changed(modem, ur);
729 return TCORE_HOOK_RETURN_CONTINUE;
735 co_ps = tcore_plugin_ref_core_object(target_plg, CORE_OBJECT_TYPE_PS);
737 return TCORE_HOOK_RETURN_CONTINUE;
739 if (cmd == TREQ_MODEM_POWER_ON) {
740 return __ps_handle_modem_power_on(modem, ur);
742 if (FALSE == tcore_ps_any_context_activating_activated(co_ps, &value)) {
743 ps_dbg_ex_modem(modem, "No activating/activated context present");
744 /* Block PS always-on while network operations. */
745 __ps_modem_get_mode_pref_change(modem, ur);
746 __ps_modem_set_hook_flag(modem, cmd);
747 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
748 return TCORE_HOOK_RETURN_CONTINUE;
751 ps_info_ex_modem(modem, "Value returned [%d]", value);
752 if (CONTEXT_STATE_ACTIVATED == value) {
753 ps_dbg_ex_modem(modem, "Internet/mms/tethering Activated/Activating context present need to deactivate them");
754 if (cmd == TREQ_NETWORK_SEARCH || cmd == TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH) {
755 g_hash_table_iter_init(&iter, modem->services);
756 while (g_hash_table_iter_next(&iter, &key, &service) == TRUE)
757 _ps_service_disconnect_internet_mms_tethering_contexts(service);
759 rv = tcore_ps_deactivate_contexts(co_ps);
760 if (cmd == TREQ_MODEM_SET_FLIGHTMODE || cmd == TREQ_MODEM_POWER_OFF)
761 __ps_set_deactivation_timeout(modem, 10);
762 if (rv != TCORE_RETURN_SUCCESS) {
763 ps_dbg_ex_modem(modem, "fail to deactivation");
764 return TCORE_HOOK_RETURN_CONTINUE;
767 } else if (CONTEXT_STATE_ACTIVATING == value) {
768 if ((cmd == TREQ_MODEM_SET_FLIGHTMODE) || (cmd == TREQ_MODEM_POWER_OFF)) {
769 ps_info_ex_modem(modem, "No need to stop these request for pdp in activating state ");
770 return TCORE_HOOK_RETURN_CONTINUE;
772 ps_dbg_ex_modem(modem, "For rest command will wait for activation successful ");
775 if (!modem->work_queue) {
776 ps_err_ex_modem(modem, "no queue present unable to handle request");
777 return TCORE_HOOK_RETURN_CONTINUE;
780 job_cnt = ps_util_get_waiting_job_count(modem->work_queue, cmd);
782 ps_err_ex_modem(modem, "duplicated job for cmd(%d)", cmd);
784 __ps_handle_waiting_job(ur, cmd);
785 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
788 ps_dbg_ex_modem(modem, "Deactivation request is sent, wait for call disconnect notification ");
790 if (TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH == cmd) {
791 UserRequest *ur_pending = NULL;
792 ur_pending = ps_util_pop_waiting_job(modem->work_queue, TREQ_NETWORK_SEARCH);
795 ps_dbg_ex_modem(modem, "no pendig search request");
796 tcore_user_request_set_response_hook(ur, __ps_hook_response_cb, modem);
797 return TCORE_HOOK_RETURN_CONTINUE;
799 __ps_handle_cancel_manual_search(modem, ur, ur_pending);
800 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
804 ret = ps_util_add_waiting_job(modem->work_queue, cmd, ur);
806 ps_err_ex_modem(modem, "fail to add the request to queue");
807 return TCORE_HOOK_RETURN_CONTINUE;
810 __ps_modem_get_mode_pref_change(modem, ur);
811 __ps_modem_set_hook_flag(modem, cmd);
812 return TCORE_HOOK_RETURN_STOP_PROPAGATION;
815 guchar _ps_hook_get_hook_flag(ps_modem_t *modem)
817 g_return_val_if_fail(modem != NULL, FALSE);
818 return modem->hook_flag;
821 GQueue *_ps_hook_ref_work_queue(ps_modem_t *modem)
823 g_return_val_if_fail(modem != NULL, NULL);
824 return modem->work_queue;
827 void _ps_hook_cp_reset_send_pending_request_response(ps_modem_t *modem)
829 gpointer queue_data = NULL;
831 ps_info_ex_modem(modem, "Entered");
832 queue_data = g_queue_pop_head(modem->work_queue);
834 struct work_queue_data *wqd = queue_data;
836 enum tcore_request_command cmd = tcore_user_request_get_command(wqd->ur);
838 if (cmd == TREQ_NETWORK_SEARCH) {
839 struct tresp_network_search search_rsp;
840 memset(&search_rsp, 0, sizeof(struct tresp_network_search));
842 search_rsp.result = TCORE_RETURN_FAILURE;
843 search_rsp.list_count = 0;
844 tcore_user_request_send_response(wqd->ur, TRESP_NETWORK_SEARCH,
845 sizeof(struct tresp_network_search), &search_rsp);
846 } else if (cmd == TREQ_NETWORK_SET_PLMN_SELECTION_MODE) {
847 struct tresp_network_set_plmn_selection_mode set_plmn_mode_rsp;
848 memset(&set_plmn_mode_rsp, 0, sizeof(struct tresp_network_set_plmn_selection_mode));
850 set_plmn_mode_rsp.result = TCORE_RETURN_FAILURE;
851 tcore_user_request_send_response(wqd->ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE,
852 sizeof(struct tresp_network_set_plmn_selection_mode), &set_plmn_mode_rsp);
853 } else if (cmd == TREQ_NETWORK_SET_MODE) {
854 struct tresp_network_set_mode setmode_rsp;
855 memset(&setmode_rsp, 0, sizeof(struct tresp_network_set_mode));
857 setmode_rsp.result = TCORE_RETURN_FAILURE;
858 tcore_user_request_send_response(wqd->ur, TRESP_NETWORK_SET_MODE,
859 sizeof(struct tresp_network_set_mode), &setmode_rsp);
860 } else if (cmd == TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH) {
861 struct tresp_network_set_cancel_manual_search search_cancel_rsp;
862 memset(&search_cancel_rsp, 0, sizeof(struct tresp_network_set_cancel_manual_search));
864 search_cancel_rsp.result = TCORE_RETURN_FAILURE;
865 tcore_user_request_send_response(wqd->ur, TRESP_NETWORK_SET_CANCEL_MANUAL_SEARCH,
866 sizeof(struct tresp_network_set_cancel_manual_search), &search_cancel_rsp);
867 } else if (cmd == TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION) {
868 struct tresp_network_set_default_data_subscription default_data_rsp;
869 memset(&default_data_rsp, 0, sizeof(struct tresp_network_set_default_data_subscription));
871 default_data_rsp.result = TCORE_RETURN_FAILURE;
872 tcore_user_request_send_response(wqd->ur, TRESP_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION,
873 sizeof(struct tresp_network_set_default_data_subscription), &default_data_rsp);
874 } else if (cmd == TREQ_MODEM_SET_FLIGHTMODE) {
875 struct tresp_modem_set_flightmode set_flight_mode;
876 memset(&set_flight_mode, 0, sizeof(struct tresp_modem_set_flightmode));
878 set_flight_mode.result = TCORE_RETURN_FAILURE;
879 tcore_user_request_send_response(wqd->ur, TRESP_MODEM_SET_FLIGHTMODE,
880 sizeof(struct tresp_modem_set_flightmode), &set_flight_mode);
881 } else if (cmd == TREQ_MODEM_POWER_OFF) {
882 struct tresp_modem_power_off set_power_off;
883 memset(&set_power_off, 0, sizeof(struct tresp_modem_power_off));
885 set_power_off.result = TCORE_RETURN_FAILURE;
886 tcore_user_request_send_response(wqd->ur, TRESP_MODEM_POWER_OFF,
887 sizeof(struct tresp_modem_power_off), &set_power_off);
889 } else if (cmd == TREQ_MODEM_POWER_LOW) {
890 struct tresp_modem_power_low set_power_low;
891 memset(&set_power_low, 0, sizeof(struct tresp_modem_power_low));
893 set_power_low.result = TCORE_RETURN_FAILURE;
894 tcore_user_request_send_response(wqd->ur, TRESP_MODEM_POWER_LOW,
895 sizeof(struct tresp_modem_power_low), &set_power_low);
897 } else if (cmd == TREQ_SIM_SET_POWERSTATE) {
898 struct tresp_sim_set_powerstate set_power;
899 memset(&set_power, 0, sizeof(struct tresp_sim_set_powerstate));
901 set_power.result = TCORE_RETURN_FAILURE;
902 tcore_user_request_send_response(wqd->ur, TRESP_SIM_SET_POWERSTATE,
903 sizeof(struct tresp_sim_set_powerstate), &set_power);
906 ps_err_ex_modem(modem, "Unexpected command ");
908 tcore_user_request_unref(wqd->ur);
913 queue_data = g_queue_pop_head(modem->work_queue);
917 void _ps_hook_send_pending_user_request(ps_modem_t *modem)
919 TcorePlugin *plugin = NULL;
920 CoreObject *co_network = NULL;
921 CoreObject *co_modem = NULL;
922 CoreObject *co_sim = NULL;
923 gpointer queue_data = NULL;
925 co_modem = _ps_modem_ref_co_modem(modem);
926 plugin = tcore_object_ref_plugin(co_modem);
927 co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK);
928 co_sim = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SIM);
930 ps_dbg_ex_modem(modem, "Extracting the user request from the work queue");
932 queue_data = g_queue_pop_head(modem->work_queue);
934 struct work_queue_data *wqd = queue_data;
935 ps_info_ex_modem(modem, " sending Pending request [%x]", wqd->id);
937 ps_dbg_ex_modem(modem, "Setting responce hook for request ");
938 tcore_user_request_set_response_hook(wqd->ur, __ps_hook_response_cb, modem);
941 case TREQ_NETWORK_SEARCH:
942 case TREQ_NETWORK_SET_MODE:
943 case TREQ_NETWORK_SET_PLMN_SELECTION_MODE:
944 case TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION: {
946 TcorePlugin *modem_plugin, *ur_modem_plugin;
948 modem_name = tcore_user_request_get_modem_name(wqd->ur);
952 modem_plugin = tcore_object_ref_plugin(co_modem);
953 ur_modem_plugin = tcore_server_find_plugin(tcore_plugin_ref_server(modem_plugin), modem_name);
954 if (modem_plugin != ur_modem_plugin) {
955 ps_info_ex_modem(modem, "request modem (%s) not matched current modem(%s)",
956 modem_name, tcore_server_get_cp_name_by_plugin(modem_plugin));
957 /* Network search request enqueued for other sim, so dispatch it */
958 if (wqd->id == TREQ_NETWORK_SEARCH) {
959 CoreObject *co_other_network;
961 co_other_network = tcore_plugin_ref_core_object(ur_modem_plugin, CORE_OBJECT_TYPE_NETWORK);
962 if (co_other_network == NULL) {
963 ps_warn_ex_modem(modem, "No network core object in other modem plugin");
965 if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_other_network, wqd->ur))
966 ps_err_ex_modem(modem, "Failed to dispatch ");
975 if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_network, wqd->ur))
976 ps_err_ex_modem(modem, "Failed to dispatch ");
980 case TREQ_MODEM_SET_FLIGHTMODE:
981 case TREQ_MODEM_POWER_OFF: {
983 TcorePlugin *modem_plugin, *ur_modem_plugin;
985 modem_name = tcore_user_request_get_modem_name(wqd->ur);
989 modem_plugin = tcore_object_ref_plugin(co_modem);
990 ur_modem_plugin = tcore_server_find_plugin(tcore_plugin_ref_server(modem_plugin), modem_name);
991 if (modem_plugin != ur_modem_plugin) {
992 ps_info_ex_modem(modem, "request modem (%s) not matched current modem(%s)",
993 modem_name, tcore_server_get_cp_name_by_plugin(modem_plugin));
994 /* Flight mode request enqueued for other sim, so dispatch it */
995 if (wqd->id == TREQ_MODEM_SET_FLIGHTMODE) {
996 CoreObject *co_other_modem;
998 co_other_modem = tcore_plugin_ref_core_object(ur_modem_plugin, CORE_OBJECT_TYPE_MODEM);
999 if (co_other_modem == NULL) {
1000 ps_warn_ex_modem(modem, "No modem core object in other modem plugin");
1002 if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_other_modem, wqd->ur))
1003 ps_err_ex_modem(modem, "Failed to dispatch ");
1014 if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_modem, wqd->ur))
1015 ps_err_ex_modem(modem, "Failed to dispatch ");
1019 case TREQ_MODEM_POWER_LOW:
1020 if (modem->hook_flag & PS_NETWORK_SET_POWER_LOW)
1021 if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_modem, wqd->ur))
1022 err("Failed to dispatch ");
1025 case TREQ_SIM_SET_POWERSTATE:
1026 if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_sim, wqd->ur))
1027 ps_err_ex_modem(modem, "Failed to dispatch ");
1031 ps_err_ex_modem(modem, "No expected request ");
1035 /* Freeing Allocated memory*/
1037 queue_data = g_queue_pop_head(modem->work_queue);
1040 ps_dbg_ex_modem(modem, "All pending request sent ");
1043 gboolean _ps_hook_add_modem_hooks(ps_modem_t *modem)
1046 g_return_val_if_fail(modem != NULL, FALSE);
1047 s = tcore_plugin_ref_server(_ps_modem_ref_plugin(modem));
1049 /* Adding hooks for special Network Requests */
1050 tcore_server_add_request_hook(s, TREQ_NETWORK_SEARCH, ps_handle_hook, modem);
1051 tcore_server_add_request_hook(s, TREQ_NETWORK_SET_PLMN_SELECTION_MODE, ps_handle_hook, modem);
1052 tcore_server_add_request_hook(s, TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH, ps_handle_hook, modem);
1053 tcore_server_add_request_hook(s, TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION, ps_handle_hook, modem);
1054 tcore_server_add_request_hook(s, TREQ_SIM_SET_POWERSTATE, ps_handle_hook, modem);
1055 tcore_server_add_request_hook(s, TREQ_MODEM_SET_FLIGHTMODE, ps_handle_hook, modem);
1056 tcore_server_add_request_hook(s, TREQ_MODEM_POWER_OFF, ps_handle_hook, modem);
1057 tcore_server_add_request_hook(s, TREQ_MODEM_POWER_LOW, ps_handle_hook, modem);
1058 tcore_server_add_request_hook(s, TREQ_MODEM_POWER_ON, ps_handle_hook, modem);
1063 gboolean _ps_hook_free_modem_hooks(ps_modem_t *modem)
1068 #endif /* TIZEN_SUPPORT_REQUEST_HOOK_PDP_CONTROL */