/* * * tel-plugin-vpc * * Copyright (C) 2013 Intel Corporation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include #include #include #include #include #include "vpc.h" static int registered = FALSE; static TcorePlugin * find_modem_plugin(Server *s) { TcorePlugin *plugin = tcore_server_find_plugin(s, "mfld_blackbay0"); if (plugin != NULL) return plugin; plugin = tcore_server_find_plugin(s, "clovertrail_geek0"); return plugin; } static inline int audio_device_converter(int device) { switch (device) { case 0: return DISCONNECT; case CALL_SOUND_PATH_HANDSET: return DEVICE_OUT_EARPIECE; case CALL_SOUND_PATH_SPEAKER: return DEVICE_OUT_SPEAKER; case CALL_SOUND_PATH_HEADSET: return DEVICE_OUT_WIRED_HEADSET; case CALL_SOUND_PATH_BLUETOOTH: return DEVICE_OUT_BLUETOOTH; default: err("device Id not recognized, use default device (earpiece)"); return DEVICE_OUT_EARPIECE; } } static void prepare_and_send_pending_request (TcorePlugin *plugin, unsigned int plugin_type, const char *at_cmd, const char *prefix, enum tcore_at_command_type at_cmd_type, TcorePendingResponseCallback callback) { TcoreATRequest *req; TcoreHal *hal; CoreObject *co; TcorePending *pending ; co = tcore_plugin_ref_core_object(plugin, plugin_type); hal = tcore_object_get_hal(co); dbg("hal: %p", hal); pending = tcore_pending_new(co, 0); if (pending == NULL) { err("Pending is NULL"); return; } req = tcore_at_request_new(at_cmd, prefix, at_cmd_type); if (req == NULL) { err("Create request failed"); free(pending); return; } dbg("cmd : %s, prefix(if any) :%s, cmd_len : %d", req->cmd, req->prefix, strlen(req->cmd)); tcore_pending_set_request_data(pending, 0, req); tcore_pending_set_response_callback(pending, callback, NULL); tcore_pending_link_user_request(pending, NULL); tcore_hal_send_request(hal, pending); } static void on_screen_status_changed(keynode_t *key, void* data) { TcorePlugin *plugin; int state; dbg("Entry"); plugin = (TcorePlugin *)data; if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) return; state = vconf_keynode_get_int(key); if (state == VCONFKEY_PM_STATE_NORMAL) /* screen on, enable URC */ prepare_and_send_pending_request(plugin, CORE_OBJECT_TYPE_NETWORK, "AT+CREG=2;+CGREG=2;+XCSQ=1;+XMER=1;+XFDOR=3;+CREG?;+CGREG?", NULL, TCORE_AT_NO_RESULT, NULL); else if (state == VCONFKEY_PM_STATE_LCDOFF) /* screen off, disable URC */ prepare_and_send_pending_request(plugin, CORE_OBJECT_TYPE_NETWORK, "AT+CREG=0;+CGREG=0;+XCSQ=0;+XMER=0;+XFDOR=2", NULL, TCORE_AT_NO_RESULT, NULL); } static enum tcore_hook_return on_hook_call_end(Server *s, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) { TcorePlugin *plugin = find_modem_plugin(s); if (plugin == NULL) { warn("Warning: can't find modem plugin"); return TCORE_HOOK_RETURN_CONTINUE; } vpc_disable(); /* amc disable */ // usleep(1000); /* Time to disable MSIC... */ prepare_and_send_pending_request(plugin, CORE_OBJECT_TYPE_CALL, "AT+XDRV=40,3,3", NULL, TCORE_AT_NO_RESULT, NULL); /* Disable AMC_I2S1_RX */ prepare_and_send_pending_request(plugin, CORE_OBJECT_TYPE_CALL, "AT+XDRV=40,3,4", NULL, TCORE_AT_NO_RESULT, NULL); /* Disable AMC_I2S2_RX */ /* amc route: AMC_RADIO_RX => AMC_PCM_GENERALD */ prepare_and_send_pending_request(plugin, CORE_OBJECT_TYPE_CALL, "AT+XDRV=40,6,0,4", NULL, TCORE_AT_NO_RESULT, NULL); // usleep(80000); /* Time to Disable modem I2S... */ return TCORE_HOOK_RETURN_CONTINUE; } static enum tcore_hook_return on_hook_set_sound_path(Server *s, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) { const struct tnoti_call_sound_path *sound_path = data; int devId = audio_device_converter(sound_path->path); dbg("sound_path->path <%d> devId <%d>",sound_path->path, devId); vpc_enable(MODE_IN_CALL, devId); return TCORE_HOOK_RETURN_CONTINUE; } static enum tcore_hook_return on_hook_register_notification(Server *s, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) { /* avoid the hooks are registered repeatedly */ TcorePlugin *plugin = find_modem_plugin(s); if (plugin == NULL) return TCORE_HOOK_RETURN_CONTINUE; if (registered == TRUE) return TCORE_HOOK_RETURN_CONTINUE; tcore_server_add_notification_hook(s, TNOTI_CALL_SOUND_PATH, on_hook_set_sound_path, NULL); tcore_server_add_notification_hook(s, TNOTI_CALL_STATUS_IDLE, on_hook_call_end, NULL); vconf_notify_key_changed(VCONFKEY_PM_STATE, on_screen_status_changed, plugin); registered = TRUE; return TCORE_HOOK_RETURN_CONTINUE; } static gboolean on_load() { dbg("i'm load!"); return TRUE; } static gboolean on_init(TcorePlugin *p) { Server *s; if (p == NULL) return FALSE; vpc_init(); s = tcore_plugin_ref_server(p); tcore_server_add_notification_hook(s, TNOTI_MODEM_POWER, on_hook_register_notification, NULL); dbg("i'm init!"); return TRUE; } static void on_unload(TcorePlugin *p) { Server *s; if (p == NULL) return; s = tcore_plugin_ref_server(p); tcore_server_remove_notification_hook(s, on_hook_set_sound_path); tcore_server_remove_notification_hook(s, on_hook_call_end); vconf_ignore_key_changed(VCONFKEY_PM_STATE, on_screen_status_changed); registered = FALSE; vpc_cleanup(); dbg("i'm unload"); } struct tcore_plugin_define_desc plugin_define_desc = { .name = "vpc", .priority = TCORE_PLUGIN_PRIORITY_MID, .version = PLUGIN_VERSION, .load = on_load, .init = on_init, .unload = on_unload };