blob: e92f31fab9da700cf746bf416556e7a17f986bfb [file] [log] [blame]
/* ST-Ericsson U300 RIL
**
** Copyright (C) ST-Ericsson AB 2008-2010
** Copyright 2006, The Android Open Source Project
**
** 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.
**
** Based on the Android ril daemon and reference RIL by
** The Android Open Source Project.
**
** Heavily modified for ST-Ericsson U300 modems.
** Author: Christian Bejram <christian.bejram@stericsson.com>
*/
#include <stdlib.h>
#include <string.h>
#include <telephony/ril.h>
#include <assert.h>
#include "marvell-ril.h"
#include "ril-requestdatahandler.h"
#include "ril-sim.h"
/* Handler functions. The names are because we cheat by including
* ril_commands.h from rild. In here we generate local allocations
* of the data representations, as well as free:ing them after
* they've been handled.
*
* This design might not be ideal, but considering the alternatives,
* it's good enough.
*/
static void *dummyDispatch(void *data, size_t datalen);
#define dispatchCdmaSms dummyDispatch
#define dispatchCdmaSmsAck dummyDispatch
#define dispatchCdmaBrSmsCnf dummyDispatch
#define dispatchRilCdmaSmsWriteArgs dummyDispatch
#define dispatchDataCall dispatchStrings
#define dispatchVoiceRadioTech dummyDispatch
#define dispatchCdmaSubscriptionSource dummyDispatch
#define dispatchNVReadItem dummyDispatch
#define dispatchNVWriteItem dummyDispatch
#define dispatchUiccSubscripton dummyDispatch
#define dispatchRadioCapability dummyDispatch
static void *dispatchCallForward(void *data, size_t datalen);
static void *dispatchDial(void *data, size_t datalen);
static void *dispatchSIM_APDU(void *data, size_t datalen);
static void *dispatchSIM_IO(void *data, size_t datalen);
static void *dispatchSmsWrite(void *data, size_t datalen);
static void *dispatchString(void *data, size_t datalen);
static void *dispatchStrings(void *data, size_t datalen);
static void *dispatchRaw(void *data, size_t datalen);
static void *dispatchVoid(void *data, size_t datalen);
static void *dispatchGsmBrSmsCnf(void *data, size_t datalen);
static void *dispatchNetworkSelectionManual(void *data, size_t datalen);
static void *dispatchSetInitialAttachApn(void *data, size_t datalen);
static void *dispatchImsSms(void *data, size_t datalen);
static void *dispatchDataProfile(void *data, size_t datalen);
static void *dispatchSimAuthentication(void *data, size_t datalen);
#ifdef MARVELL_EXTENDED
static void *dispatchSIM_contact(void *data, size_t datalen);
static void *dispatchCPBSSet(void *data, size_t datalen);
static void *dispatchDialEmergency(void *data, size_t datalen);
static void *dispatchEcallOnly(void *data, size_t datalen);
static void *dispatchIPDNS(void *data, size_t datalen);
static void *dispatchZGDCONT(void *data, size_t datalen);
#endif
#define dispatchInts dispatchRaw
static void dummyResponse(void);
#define responseCallForwards dummyResponse
#define responseCallList dummyResponse
#define responseCellList dummyResponse
#define responseContexts dummyResponse
#define responseInts dummyResponse
#define responseRaw dummyResponse
#define responseSIM_IO dummyResponse
#define responseSMS dummyResponse
#define responseString dummyResponse
#define responseStrings dummyResponse
#define responseVoid dummyResponse
//for ubus.Add by yanglei
#define responseRadioStateChanged dummyResponse
#define responseSimStatus dummyResponse
#define responseRilSignalStrength dummyResponse
#define responseDataCallList dummyResponse
#define responseGsmBrSmsCnf dummyResponse
#define responseCdmaBrSmsCnf dummyResponse
#define responseSetupDataCall dummyResponse
#define responseCellInfoList dummyResponse
#define responseHardwareConfig dummyResponse
#define responseDcRtInfo dummyResponse
#define responseRadioCapability dummyResponse
#define responseSSData dummyResponse
#ifdef MARVELL_EXTENDED
#define responseSIM_contact dummyResponse
#define responseCIDState dummyResponse
#define responsePDPIPAPN dummyResponse
#define responseEcallOnlyInfo dummyResponse
#define responseZROAM dummyResponse
#define responsePacketFilterList dummyResponse
#endif
typedef struct _RilCommandInfo {
int requestId;
void *(*dispatchFunction) (void *data, size_t datalen);
void (*responseFunction) (void);
} RilCommandInfo;
/* RILD made me do it! */
static RilCommandInfo s_commandInfo[] = {
#include <ril_commands.h>
};
#ifdef MARVELL_EXTENDED
static RilCommandInfo s_commandInfo_ext[] = {
#include <ril_commands_ext.h>
};
#endif
static void *dummyDispatch(void *data, size_t datalen)
{
UNUSED(data);
UNUSED(datalen);
return 0;
}
static void dummyResponse(void)
{
return;
}
/**
* dupRequestData will copy the data pointed to by *data, returning a pointer
* to a freshly allocated representation of the data.
*/
void *dupRequestData(int requestId, void *data, size_t datalen)
{
#ifdef MARVELL_EXTENDED
if (requestId < 1 || (requestId >= (int32_t)NUM_ELEMS(s_commandInfo) && requestId < RIL_REQUEST_EXT_BASE)
|| requestId >= RIL_REQUEST_EXT_BASE + (int32_t)NUM_ELEMS(s_commandInfo_ext)) {
#else
if (requestId < 1 || requestId >= (int32_t)NUM_ELEMS(s_commandInfo)) {
#endif
RLOGE(dupRequestData, "%s: unsupported request code %d", __FUNCTION__, requestId);
return NULL;
}
#ifdef MARVELL_EXTENDED
RilCommandInfo *ci = requestId < RIL_REQUEST_EXT_BASE ? &s_commandInfo[requestId] : &s_commandInfo_ext[requestId - RIL_REQUEST_EXT_BASE];
#else
RilCommandInfo *ci = &s_commandInfo[requestId];
#endif
return ci->dispatchFunction(data, datalen);
}
static void *dispatchCallForward(void *data, size_t datalen)
{
RIL_CallForwardInfo *ret = (RIL_CallForwardInfo*)dispatchRaw(data, datalen);
if (ret->number)
ret->number = strdup(ret->number);
return ret;
}
static void *dispatchDial(void *data, size_t datalen)
{
UNUSED(datalen);
RIL_Dial *pdata = (RIL_Dial*)data;
RIL_Dial *ret = (RIL_Dial*)malloc(sizeof(RIL_Dial));
memcpy(ret, pdata, sizeof(RIL_Dial));
if (pdata->address)
ret->address = strdup(pdata->address);
if (pdata->uusInfo) {
ret->uusInfo = (RIL_UUS_Info *)malloc(sizeof(RIL_UUS_Info));
memcpy(ret->uusInfo, pdata->uusInfo, sizeof(RIL_UUS_Info));
if (pdata->uusInfo->uusData)
ret->uusInfo->uusData = strdup(pdata->uusInfo->uusData);
}
return ret;
}
static void *dispatchSIM_APDU(void *data, size_t datalen)
{
RIL_SIM_APDU *ret = (RIL_SIM_APDU*)dispatchRaw(data, datalen);
if (ret->data)
ret->data = strdup(ret->data);
return ret;
}
static void *dispatchSIM_IO(void *data, size_t datalen)
{
RIL_SIM_IO *ret = (RIL_SIM_IO*)dispatchRaw(data, datalen);
if (ret->path)
ret->path = strdup(ret->path);
if (ret->data)
ret->data = strdup(ret->data);
if (ret->pin2)
ret->pin2 = strdup(ret->pin2);
if (ret->aidPtr)
ret->aidPtr = strdup(ret->aidPtr);
return ret;
}
static void *dispatchSmsWrite(void *data, size_t datalen)
{
RIL_SMS_WriteArgs *ret = (RIL_SMS_WriteArgs*)dispatchRaw(data, datalen);
if (ret->pdu)
ret->pdu = strdup(ret->pdu);
if (ret->smsc)
ret->smsc = strdup(ret->smsc);
return ret;
}
static void *dispatchSimAuthentication(void *data, size_t datalen)
{
RIL_SimAuthentication *ret = (RIL_SimAuthentication*)dispatchRaw(data, datalen);
if (ret->authData)
ret->authData = strdup(ret->authData);
if (ret->aid)
ret->aid = strdup(ret->aid);
return ret;
}
static void *dispatchString(void *data, size_t datalen)
{
UNUSED(datalen);
//assert(datalen == sizeof(char *));
if (data)
return strdup((char *) data);
return NULL;
}
static void *dispatchStrings(void *data, size_t datalen)
{
char **a = (char **) data;
char **ret;
int strCount = datalen / sizeof(char *);
int i;
//assert((datalen % sizeof(char *)) == 0);
ret = (char **)malloc(strCount * sizeof(char *));
memset(ret, 0, sizeof(char *) * strCount);
for (i = 0; i < strCount; i++)
if (a[i])
ret[i] = strdup(a[i]);
else
ret[i] = NULL;
return (void *) ret;
}
static void *dispatchGsmBrSmsCnf(void *data, size_t datalen)
{
RIL_GSM_BroadcastSmsConfigInfo **a =
(RIL_GSM_BroadcastSmsConfigInfo **) data;
int count;
void **ret;
int i;
count = datalen / sizeof(RIL_GSM_BroadcastSmsConfigInfo *);
ret = (void**)malloc(count * sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
memset(ret, 0, sizeof(*ret));
for (i = 0; i < count; i++)
if (a[i])
ret[i] =
dispatchRaw(a[i], sizeof(RIL_GSM_BroadcastSmsConfigInfo));
return ret;
}
static void *dispatchSetInitialAttachApn(void *data, size_t datalen)
{
RIL_InitialAttachApn *ret = (RIL_InitialAttachApn*)dispatchRaw(data, datalen);
if (ret->apn)
ret->apn = strdup(ret->apn);
if (ret->protocol)
ret->protocol = strdup(ret->protocol);
if (ret->username)
ret->username = strdup(ret->username);
if (ret->password)
ret->password = strdup(ret->password);
return ret;
}
static void* dispatchDataProfile(void *data, size_t datalen)
{
int count = 0, i = 0;
void **ret = NULL;
RIL_DataProfileInfo **a =
(RIL_DataProfileInfo **) data;
count = datalen / sizeof(RIL_DataProfileInfo *);
ret = (void**)malloc(count * sizeof(RIL_DataProfileInfo *));
memset(ret, 0, count * sizeof(RIL_DataProfileInfo *));
for (i = 0; i < count; i++) {
if (a[i]) {
RIL_DataProfileInfo *p = NULL;
ret[i] = dispatchRaw(a[i], sizeof(RIL_DataProfileInfo));
p = (RIL_DataProfileInfo *)ret[i];
p->apn = (a[i]->apn ? strdup(a[i]->apn) : NULL);
p->protocol = (a[i]->protocol ? strdup(a[i]->protocol) : NULL);
p->user = (a[i]->user ? strdup(a[i]->user) : NULL);
p->password = (a[i]->password ? strdup(a[i]->password) : NULL);
}
}
return ret;
}
static void *dispatchImsSms(void *data, size_t datalen)
{
RIL_IMS_SMS_Message *ret = (RIL_IMS_SMS_Message*)dispatchRaw(data, datalen);
RIL_CDMA_SMS_Message *rcsm;
char **pStrings;
int countStrings;
int i;
if (RADIO_TECH_3GPP == ret->tech)
{
countStrings = (datalen - sizeof(RIL_RadioTechnologyFamily) - sizeof(uint8_t) - sizeof(int32_t)) / sizeof(char *);
if (countStrings == 2)
{
pStrings = (char **)calloc(countStrings, sizeof(char *));
for (i = 0; i < countStrings; i++)
{
if ((ret->message.gsmMessage)[i] != NULL)
{
pStrings[i] = strdup((ret->message.gsmMessage)[i]);
}
}
ret->message.gsmMessage = pStrings;
}
else
{
RLOGE(dispatchImsSms, "%s: invalid parameters.", __FUNCTION__);
free(ret);
ret = NULL;
}
}
else if (RADIO_TECH_3GPP2 == ret->tech)
{
rcsm = (RIL_CDMA_SMS_Message *)calloc(1, sizeof(RIL_CDMA_SMS_Message));
memcpy(rcsm, ret->message.cdmaMessage, sizeof(RIL_CDMA_SMS_Message));
ret->message.cdmaMessage = rcsm;
}
else
{
free(ret);
ret = NULL;
}
return ret;
}
#ifdef MARVELL_EXTENDED
static void* dispatchNetworkSelectionManual(void *data, size_t datalen)
{
RIL_OperInfo *ret = (RIL_OperInfo*)dispatchRaw(data, datalen);
if (ret->operLongStr)
ret->operLongStr = strdup(ret->operLongStr);
if (ret->operShortStr)
ret->operShortStr = strdup(ret->operShortStr);
if (ret->operNumStr)
ret->operNumStr = strdup(ret->operNumStr);
return ret;
}
//for phonebook app. Add by yanglei
static void *dispatchSIM_contact(void *data, size_t datalen)
{
RIL_CPSimContact *ret = (RIL_CPSimContact *)dispatchRaw(data, datalen);
if(ret->name)
ret->name = strdup(ret->name);
if(ret->number)
ret->number = strdup(ret->number);
return ret;
}
static void *dispatchCPBSSet(void *data, size_t datalen)
{
RIL_CPBSsetInfo *ret = (RIL_CPBSsetInfo *)dispatchRaw(data, datalen);
if(ret->password)
ret->password = strdup(ret->password);
return ret;
}
static void *dispatchDialEmergency(void *data, size_t datalen)
{
RIL_DialEmergency *ret = (RIL_DialEmergency *)dispatchRaw(data, datalen);
if(ret->number)
ret->number = strdup(ret->number);
return ret;
}
static void *dispatchEcallOnly(void *data, size_t datalen)
{
RIL_ECALLOnly *ret = (RIL_ECALLOnly *)dispatchRaw(data, datalen);
if(ret->testnum)
ret->testnum = strdup(ret->testnum);
if(ret->recfgnum)
ret->recfgnum = strdup(ret->recfgnum);
return ret;
}
static void *dispatchIPDNS(void *data, size_t datalen)
{
RIL_IPDNSInfo *ret = (RIL_IPDNSInfo *)dispatchRaw(data, datalen);
if(ret->ip_type)
ret->ip_type = strdup(ret->ip_type);
if(ret->ip)
ret->ip = strdup(ret->ip);
if(ret->gateway)
ret->gateway = strdup(ret->gateway);
if(ret->primary_dns)
ret->primary_dns = strdup(ret->primary_dns);
if(ret->secondary_dns)
ret->secondary_dns = strdup(ret->secondary_dns);
return ret;
}
static void *dispatchZGDCONT(void *data, size_t datalen)
{
RIL_ZGDCONTInfo *ret = (RIL_ZGDCONTInfo *)dispatchRaw(data, datalen);
if(ret->ip_type)
ret->ip_type = strdup(ret->ip_type);
if(ret->apn)
ret->apn = strdup(ret->apn);
return ret;
}
#endif
static void *dispatchRaw(void *data, size_t datalen)
{
void *ret = malloc(datalen);
memcpy(ret, data, datalen);
return (void *) ret;
}
static void *dispatchVoid(void *data, size_t datalen)
{
UNUSED(data);
UNUSED(datalen);
return NULL;
}
static void freeDial(void *data)
{
RIL_Dial *d = reinterpret_cast<RIL_Dial*>(data);
if (d->address)
free(d->address);
if (d->uusInfo)
{
if (d->uusInfo->uusData)
free(d->uusInfo->uusData);
free(d->uusInfo);
}
free(d);
}
static void freeStrings(void *data, size_t datalen)
{
int count = datalen / sizeof(char *);
int i;
for (i = 0; i < count; i++)
if (((char **) data)[i])
free(((char **) data)[i]);
free(data);
}
static void freeGsmBrSmsCnf(void *data, size_t datalen)
{
int count = datalen / sizeof(RIL_GSM_BroadcastSmsConfigInfo);
int i;
for (i = 0; i < count; i++)
if (((RIL_GSM_BroadcastSmsConfigInfo **) data)[i])
free(((RIL_GSM_BroadcastSmsConfigInfo **) data)[i]);
free(data);
}
static void freeSIM_APDU(void *data)
{
RIL_SIM_APDU *apdu = reinterpret_cast<RIL_SIM_APDU*>(data);
if (apdu->data)
free(apdu->data);
free(apdu);
}
static void freeSIM_IO(void *data)
{
RIL_SIM_IO *sio = reinterpret_cast<RIL_SIM_IO*>(data);
if (sio->path)
free(sio->path);
if (sio->data)
free(sio->data);
if (sio->pin2)
free(sio->pin2);
if (sio->aidPtr)
free(sio->aidPtr);
free(sio);
}
static void freeSmsWrite(void *data)
{
RIL_SMS_WriteArgs *args = reinterpret_cast<RIL_SMS_WriteArgs*>(data);
if (args->pdu)
free(args->pdu);
if (args->smsc)
free(args->smsc);
free(args);
}
static void freeCallForward(void *data)
{
RIL_CallForwardInfo *cff = reinterpret_cast<RIL_CallForwardInfo*>(data);
if (cff->number)
free(cff->number);
free(cff);
}
static void freeSetInitialAttachApn(void *data)
{
RIL_InitialAttachApn *iaapn = reinterpret_cast<RIL_InitialAttachApn*>(data);
if (iaapn->apn)
free(iaapn->apn);
if (iaapn->protocol)
free(iaapn->protocol);
if (iaapn->username)
free(iaapn->username);
if (iaapn->password)
free(iaapn->password);
free(iaapn);
}
static void freeDataProfile(void *data, size_t datalen)
{
int count = 0, i = 0;
RIL_DataProfileInfo **a =
(RIL_DataProfileInfo **) data;
count = datalen / sizeof(RIL_DataProfileInfo *);
for (i = 0; i < count; i++) {
if (a[i]) {
if (a[i]->apn) free(a[i]->apn);
if (a[i]->protocol) free(a[i]->protocol);
if (a[i]->user) free(a[i]->user);
if (a[i]->password) free(a[i]->password);
free(a[i]);
}
}
free(a);
}
#ifdef MARVELL_EXTENDED
static void freeNetworkSelectionManual(void *data)
{
RIL_OperInfo *oper = reinterpret_cast<RIL_OperInfo*>(data);
if (oper->operLongStr)
free(oper->operLongStr);
if (oper->operShortStr)
free(oper->operShortStr);
if (oper->operNumStr)
free(oper->operNumStr);
free(oper);
}
//for phonebook app. Add by yanglei
static void freeSIM_contact(void *data)
{
RIL_CPSimContact *p = (RIL_CPSimContact *)data;
if(p->name)
free(p->name);
if(p->number)
free(p->number);
free(p);
}
static void freeCPBSSet(void *data)
{
RIL_CPBSsetInfo *p = (RIL_CPBSsetInfo *)data;
if(p->password)
free(p->password);
free(p);
}
static void freeDialEmergency(void *data)
{
RIL_DialEmergency *p = (RIL_DialEmergency *)data;
if(p->number)
free(p->number);
free(p);
}
static void freeEcallOnly(void *data)
{
RIL_ECALLOnly *p = (RIL_ECALLOnly *)data;
if(p->testnum)
free(p->testnum);
if(p->recfgnum)
free(p->recfgnum);
free(p);
}
static void freeIPDNS(void *data)
{
RIL_IPDNSInfo *p = (RIL_IPDNSInfo *)data;
if (p->ip_type)
free(p->ip_type);
if (p->ip)
free(p->ip);
if (p->gateway)
free(p->gateway);
if (p->primary_dns)
free(p->primary_dns);
if (p->secondary_dns)
free(p->secondary_dns);
free(p);
}
static void freeZGDCONT(void *data)
{
RIL_ZGDCONTInfo *p = (RIL_ZGDCONTInfo *)data;
if (p->ip_type)
free(p->ip_type);
if (p->apn)
free(p->apn);
free(p);
}
#endif
static void freeImsSms(void *data)
{
RIL_IMS_SMS_Message *rism = reinterpret_cast<RIL_IMS_SMS_Message*>(data);
if (rism == NULL) return;
if (RADIO_TECH_3GPP == rism->tech)
{
free((rism->message.gsmMessage)[0]);
free((rism->message.gsmMessage)[1]);
free(rism->message.gsmMessage);
}
else if (RADIO_TECH_3GPP2 == rism->tech)
{
free(rism->message.cdmaMessage);
}
free(rism);
}
static void freeSimAuthentication(void *data)
{
RIL_SimAuthentication *simAut = reinterpret_cast<RIL_SimAuthentication*>(data);
if (simAut->authData)
free(simAut->authData);
if (simAut->aid)
free(simAut->aid);
free(simAut);
}
void freeRequestData(int requestId, void *data, size_t datalen)
{
#ifdef MARVELL_EXTENDED
if (requestId < 1 || (requestId >= (int32_t)NUM_ELEMS(s_commandInfo) && requestId < RIL_REQUEST_EXT_BASE)
|| requestId >= RIL_REQUEST_EXT_BASE + (int32_t)NUM_ELEMS(s_commandInfo_ext)) {
#else
if (requestId < 1 || requestId >= (int32_t)NUM_ELEMS(s_commandInfo)) {
#endif
RLOGE(freeRequestData, "%s: unsupported request code %d", __FUNCTION__, requestId);
return;
}
#ifdef MARVELL_EXTENDED
RilCommandInfo *ci = requestId < RIL_REQUEST_EXT_BASE ? &s_commandInfo[requestId] : &s_commandInfo_ext[requestId - RIL_REQUEST_EXT_BASE];
#else
RilCommandInfo *ci = &s_commandInfo[requestId];
#endif
if (ci->dispatchFunction == dispatchInts ||
ci->dispatchFunction == dispatchRaw ||
ci->dispatchFunction == dispatchString) {
if (data)
free(data);
} else if (ci->dispatchFunction == dispatchStrings)
freeStrings(data, datalen);
else if (ci->dispatchFunction == dispatchSIM_APDU)
freeSIM_APDU(data);
else if (ci->dispatchFunction == dispatchSIM_IO)
freeSIM_IO(data);
else if (ci->dispatchFunction == dispatchDial)
freeDial(data);
else if (ci->dispatchFunction == dispatchVoid) {
} else if (ci->dispatchFunction == dispatchCallForward)
freeCallForward(data);
else if (ci->dispatchFunction == dispatchSmsWrite)
freeSmsWrite(data);
else if (ci->dispatchFunction == dispatchGsmBrSmsCnf)
freeGsmBrSmsCnf(data, datalen);
else if (ci->dispatchFunction == dispatchSetInitialAttachApn)
freeSetInitialAttachApn(data);
else if (ci->dispatchFunction == dispatchDataProfile)
freeDataProfile(data, datalen);
#ifdef MARVELL_EXTENDED
else if (ci->dispatchFunction == dispatchNetworkSelectionManual)
freeNetworkSelectionManual(data);
else if (ci->dispatchFunction == dispatchSIM_contact)
freeSIM_contact(data);
else if (ci->dispatchFunction == dispatchCPBSSet)
freeCPBSSet(data);
else if (ci->dispatchFunction == dispatchDialEmergency)
freeDialEmergency(data);
else if (ci->dispatchFunction == dispatchEcallOnly)
freeEcallOnly(data);
else if (ci->dispatchFunction == dispatchIPDNS)
freeIPDNS(data);
else if (ci->dispatchFunction == dispatchZGDCONT)
freeZGDCONT(data);
#endif
else if (ci->dispatchFunction == dispatchImsSms)
freeImsSms(data);
else if (ci->dispatchFunction == dispatchSimAuthentication)
freeSimAuthentication(data);
}