diff options
author | PaulK <contact@paulk.fr> | 2011-12-31 16:46:51 +0100 |
---|---|---|
committer | PaulK <contact@paulk.fr> | 2011-12-31 16:46:51 +0100 |
commit | 852feed67ca215589a223f6a51a64673b21af35f (patch) | |
tree | c5bd9be5df676aa5259ebaaa0fd0cfff658c4cf1 /gen.c | |
parent | 5a5ce9424d3ea0c7734addd7ac835900c6cf3c4a (diff) | |
download | hardware_ril_samsung-ril-852feed67ca215589a223f6a51a64673b21af35f.zip hardware_ril_samsung-ril-852feed67ca215589a223f6a51a64673b21af35f.tar.gz hardware_ril_samsung-ril-852feed67ca215589a223f6a51a64673b21af35f.tar.bz2 |
Added RFS functions and IPC_GEN_PHONE_RES proper handling, applied to data
Diffstat (limited to 'gen.c')
-rw-r--r-- | gen.c | 154 |
1 files changed, 154 insertions, 0 deletions
@@ -0,0 +1,154 @@ +/** + * This file is part of samsung-ril. + * + * Copyright (C) 2011 Paul Kocialkowski <contact@oaulk.fr> + * + * samsung-ril is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * samsung-ril is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with samsung-ril. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#define LOG_TAG "RIL-GEN" +#include <utils/Log.h> + +#include "samsung-ril.h" +#include "util.h" + +struct ipc_gen_phone_res_expect ipc_gen_phone_res_expects[0x20]; +int ipc_gen_phone_res_id = 0; + +/** + * IPC_GEN_PHONE_RES has shared aseq (in the header), group, index and type (in the data) + * On this implementation, we just check aseq and command (group and index). + * aseq permits to identify the queued request and do what's wanted. + * It can be either call a function with the struct ipc_message_info, + * complete the request to RILJ (with or without an error), + * return to RILJ if there is an error in this response. + * + * It would have been possible to deal with group, index and type only and use + * callback functions. Though, what is currently being used is more a "standard" + * error catch system, that requires less code (no particular function), while + * it also permits using custom functions, when IPC_GEN_PHONE_RES code is + * request-specific. + * + * On a custom function, don't forget to get a clean new aseq if you're going to + * send some data to the modem, just liek this: + * aseq = ril_request_reg_id(reqGetToken(info->aseq)); + */ + +int ipc_gen_phone_res_id_new(void) +{ + ipc_gen_phone_res_id++; + ipc_gen_phone_res_id %= 0x20; + return ipc_gen_phone_res_id; +} + +int ipc_gen_phone_res_get_id(unsigned char aseq) +{ + int i; + + for(i=0 ; i < 0x20 ; i++) + if(ipc_gen_phone_res_expects[i].aseq == aseq) + return i; + + return -1; +} + +void ipc_gen_phone_res_clean_id(int id) +{ + ipc_gen_phone_res_expects[id].aseq = 0; + ipc_gen_phone_res_expects[id].command = 0; + ipc_gen_phone_res_expects[id].func = NULL; + ipc_gen_phone_res_expects[id].to_complete = 0; + ipc_gen_phone_res_expects[id].to_abort = 0; +} + +void ipc_gen_phone_res_expect_to_func(unsigned char aseq, unsigned short command, + void (*func)(struct ipc_message_info *info)) +{ + int id = ipc_gen_phone_res_id_new(); + + ipc_gen_phone_res_expects[id].aseq = aseq; + ipc_gen_phone_res_expects[id].command = command; + ipc_gen_phone_res_expects[id].func = func; + ipc_gen_phone_res_expects[id].to_complete = 0; + ipc_gen_phone_res_expects[id].to_abort = 0; +} + +void ipc_gen_phone_res_expect_to_complete(unsigned char aseq, unsigned short command) +{ + int id = ipc_gen_phone_res_id_new(); + + ipc_gen_phone_res_expects[id].aseq = aseq; + ipc_gen_phone_res_expects[id].command = command; + ipc_gen_phone_res_expects[id].func = NULL; + ipc_gen_phone_res_expects[id].to_complete = 1; + ipc_gen_phone_res_expects[id].to_abort = 0; +} + +void ipc_gen_phone_res_expect_to_abort(unsigned char aseq, unsigned short command) +{ + int id = ipc_gen_phone_res_id_new(); + + ipc_gen_phone_res_expects[id].aseq = aseq; + ipc_gen_phone_res_expects[id].command = command; + ipc_gen_phone_res_expects[id].func = NULL; + ipc_gen_phone_res_expects[id].to_complete = 0; + ipc_gen_phone_res_expects[id].to_abort = 1; +} + +void ipc_gen_phone_res(struct ipc_message_info *info) +{ + struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data; + int id = ipc_gen_phone_res_get_id(info->aseq); + RIL_Errno e; + int rc; + + // In this case, it can be a real error or we just didn't queue + if(id < 0) { + LOGD("aseq: 0x%x not found in the IPC_GEN_PHONE_RES queue", info->aseq); + return; + } + + LOGD("aseq: 0x%x found in the IPC_GEN_PHONE_RES queue!", info->aseq); + + if(ipc_gen_phone_res_expects[id].command != IPC_COMMAND(phone_res)) { + LOGE("IPC_GEN_PHONE_RES aseq (0x%x) doesn't match the queued one with command (0x%x)", + ipc_gen_phone_res_expects[id].aseq, ipc_gen_phone_res_expects[id].command); + + if(ipc_gen_phone_res_expects[id].func != NULL) { + LOGE("Not safe to run the custom function, reporting generic failure"); + RIL_onRequestComplete(reqGetToken(ipc_gen_phone_res_expects[id].aseq), RIL_E_GENERIC_FAILURE, NULL, 0); + } + } + + if(ipc_gen_phone_res_expects[id].func != NULL) { + ipc_gen_phone_res_expects[id].func(info); + ipc_gen_phone_res_clean_id(id); + return; + } + + rc = ipc_gen_phone_res_check(phone_res); + if(rc < 0) + e = RIL_E_GENERIC_FAILURE; + else + e = RIL_E_SUCCESS; + + if(ipc_gen_phone_res_expects[id].to_complete || (ipc_gen_phone_res_expects[id].to_abort && rc < 0)) { + RIL_onRequestComplete(reqGetToken(ipc_gen_phone_res_expects[id].aseq), e, NULL, 0); + ipc_gen_phone_res_clean_id(id); + return; + } + + ipc_gen_phone_res_clean_id(id); +} |