blob: 78f0113fdcd78b485837608efce2d6641e7e9aaf [file] [log] [blame]
/*
* Copyright (C) 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.
*/
#include <alloca.h>
#include <stdlib.h>
#include <stdio.h>
#include <cutils/jstring.h>
#include <stdlib.h>
#include <binder/Parcel.h>
#include <string.h>
#include <strings.h>
#include <log/log.h>
#include<iconv.h>
#include "common.h"
#include "ss.h"
#undef LOG_TAG
#define LOG_TAG "DEMO_SS"
static int TOA_International = 0x91;
static int TOA_Unknown = 0x81;
static const int SERVICE_CLASS_NONE = 0; // no user input
static const int SERVICE_CLASS_VOICE = (1 << 0);
static const int SERVICE_CLASS_DATA = (1 << 1); //synonym for 16+32+64+128
static const int SERVICE_CLASS_FAX = (1 << 2);
static const int SERVICE_CLASS_SMS = (1 << 3);
static const int SERVICE_CLASS_DATA_SYNC = (1 << 4);
static const int SERVICE_CLASS_DATA_ASYNC = (1 << 5);
static const int SERVICE_CLASS_PACKET = (1 << 6);
static const int SERVICE_CLASS_PAD = (1 << 7);
static const int SERVICE_CLASS_MAX = (1 << 9); // Max SERVICE_CLASS value
// Used for call barring methods below
static char* CB_FACILITY_BAOC = "AO";
static char* CB_FACILITY_BAOIC = "OI";
static char* CB_FACILITY_BAOICxH = "OX";
static char* CB_FACILITY_BAIC = "AI";
static char* CB_FACILITY_BAICr = "IR";
static char* CB_FACILITY_BA_ALL = "AB";
static char* CB_FACILITY_BA_MO = "AG";
static char* CB_FACILITY_BA_MT = "AC";
static char* CB_FACILITY_BA_SIM = "SC";
static char* CB_FACILITY_BA_FD = "FD";
// Used as parameters for call forward methods below
static const int CF_ACTION_DISABLE = 0;
static const int CF_ACTION_ENABLE = 1;
static const int CF_ACTION_INTERROGATE = 2;
static const int CF_ACTION_REGISTRATION = 3;
static const int CF_ACTION_ERASURE = 4;
static const int CF_REASON_UNCONDITIONAL = 0;
static const int CF_REASON_BUSY = 1;
static const int CF_REASON_NO_REPLY = 2;
static const int CF_REASON_NOT_REACHABLE = 3;
static const int CF_REASON_ALL = 4;
static const int CF_REASON_ALL_CONDITIONAL = 5;
static const int CF_REASON_NOT_REGISTERED = 6;
//Called line presentation
static const char* SC_CLIP = "30";
static const char* SC_CLIR = "31";
// Call Forwarding
static const char* SC_CFU = "21";
static const char* SC_CFB = "67";
static const char* SC_CFNRy = "61";
static const char* SC_CFNR = "62";
static const char* SC_CF_All = "002";
static const char* SC_CF_All_Conditional = "004";
// Call Waiting
static const char* SC_WAIT = "43";
// Call Barring
static const char* SC_BAOC = "33";
static const char* SC_BAOIC = "331";
static const char* SC_BAOICxH = "332";
static const char* SC_BAIC = "35";
static const char* SC_BAICr = "351";
static const char* SC_BA_ALL = "330";
static const char* SC_BA_MO = "333";
static const char* SC_BA_MT = "353";
// Supp Service Password registration
static const char* SC_PWD = "03";
// PIN/PIN2/PUK/PUK2
static const char* SC_PIN = "04";
static const char* SC_PIN2 = "042";
static const char* SC_PUK = "05";
static const char* SC_PUK2 = "052";
///M:For query CNAP
static const char* SC_CNAP = "300";
int toaFromString(char* s) {
if (s != NULL && strlen(s) > 0 && *s == '+') {
return TOA_International;
}
return TOA_Unknown;
}
char* scToBarringFacility(char* sc) {
if (sc == NULL) {
RLOGE("invalid call barring sc");
return NULL;
}
if (strcmp(sc, SC_BAOC) == 0) {
return CB_FACILITY_BAOC;
} else if (strcmp(sc, SC_BAOIC) == 0) {
return CB_FACILITY_BAOIC;
} else if (strcmp(sc, SC_BAOICxH) == 0) {
return CB_FACILITY_BAOICxH;
} else if (strcmp(sc, SC_BAIC) == 0) {
return CB_FACILITY_BAIC;
} else if (strcmp(sc, SC_BAICr) == 0) {
return CB_FACILITY_BAICr;
} else if (strcmp(sc, SC_BA_ALL) == 0) {
return CB_FACILITY_BA_ALL;
} else if (strcmp(sc, SC_BA_MO) == 0) {
return CB_FACILITY_BA_MO;
} else if (strcmp(sc, SC_BA_MT) == 0) {
return CB_FACILITY_BA_MT;
} else if (strcasecmp(sc, CB_FACILITY_BA_FD) == 0 ) {
return CB_FACILITY_BA_FD;
} else if (strcasecmp(sc, CB_FACILITY_BA_SIM) == 0 ) {
return CB_FACILITY_BA_SIM;
} else {
RLOGE("invalid call barring sc");
return NULL;
}
}
int scToCallForwardReason(char* sc) {
if (sc == NULL) {
RLOGE("invalid call forward sc");
return -1;
}
if (strcmp(sc, SC_CF_All) == 0) {
return CF_REASON_ALL;
} else if (strcmp(sc, SC_CFU) == 0) {
return CF_REASON_UNCONDITIONAL;
} else if (strcmp(sc, SC_CFB) == 0) {
return CF_REASON_BUSY;
} else if (strcmp(sc, SC_CFNR) == 0) {
return CF_REASON_NOT_REACHABLE;
} else if (strcmp(sc, SC_CFNRy) == 0) {
return CF_REASON_NO_REPLY;
} else if (strcmp(sc, SC_CF_All_Conditional) == 0) {
return CF_REASON_ALL_CONDITIONAL;
} else {
RLOGE("invalid call forward sc");
return -1;
}
}
int siToServiceClass(char* si)
{
if (si == NULL || strcmp(si, "null") == 0)
{
return SERVICE_CLASS_NONE;
} else {
// NumberFormatException should cause MMI fail
int serviceCode = atoi(si);
switch (serviceCode) {
case 10: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
case 11: return SERVICE_CLASS_VOICE;
case 12: return SERVICE_CLASS_SMS + SERVICE_CLASS_FAX;
case 13: return SERVICE_CLASS_FAX;
case 16: return SERVICE_CLASS_SMS;
case 19: return SERVICE_CLASS_FAX + SERVICE_CLASS_VOICE;
/*
Note for code 20:
From TS 22.030 Annex C:
"All GPRS bearer services" are not included in "All tele and bearer services"
and "All bearer services"."
....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
*/
case 20: return SERVICE_CLASS_DATA_ASYNC + SERVICE_CLASS_DATA_SYNC;
case 21: return SERVICE_CLASS_PAD + SERVICE_CLASS_DATA_ASYNC;
case 22: return SERVICE_CLASS_PACKET + SERVICE_CLASS_DATA_SYNC;
case 24: return SERVICE_CLASS_DATA_SYNC;
//don't support video
//case 24: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VIDEO;
case 25: return SERVICE_CLASS_DATA_ASYNC;
case 26: return SERVICE_CLASS_DATA_SYNC + SERVICE_CLASS_VOICE;
case 99: return SERVICE_CLASS_PACKET;
default:
RLOGW("unsupported MMI service code:%s ", si);
return SERVICE_CLASS_NONE;
}
}
}
int siToTime (char* si) {
if (si == NULL || strcmp(si, "null") == 0) {
return 0;
} else {
// NumberFormatException should cause MMI fail
return atoi(si);
}
}
bool isGBK(unsigned char* data, int len)
{
return false;
int i = 0;
while(i < len)
{
if(data[i] <= 0x7f)
{
//one byte encode
i++;
continue;
}
else
{
//two byte encode
if(data[i] >= 0x81 && data[i] <= 0xfe && data[i + 1] >= 0x40
&&data[i + 1] <= 0xfe && data[i + 1] != 0xf7)
{
i += 2;
continue;
}
else
{
return false;
}
}
}
return true;
}
int gbkToUtf8(char* src_str, size_t src_len, char* dst_str, size_t dst_len)
{
iconv_t cd;
char **pin = &src_str;
char **pout = &dst_str;
cd = iconv_open("UTF-8", "GBK");
if(cd == (iconv_t) - 1)
{
printf("iconv_open error\n");
RLOGE("iconv_open error");
return -1;
}
memset(dst_str, 0, dst_len);
if(iconv(cd, pin, &src_len, pout, &dst_len) == -1){
printf("format error or nosupport\n");
RLOGE("format error or nosupport");
return -1;
}
iconv_close(cd);
// **pout = '\0';
return 0;
}
//xxx ussiString
int sendUSSI(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 3)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
char* srcstr = argv[2];
char utf8str[64];
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(2);
writeStringToParcel(p, (const char *)argv[1]);//ussdaction
printf("srcstr:%s\n", srcstr);
printf("srcstr:%s\n", argv[2]);
if(isGBK((unsigned char *)srcstr, strlen(srcstr)))
{
if(gbkToUtf8(srcstr, strlen(srcstr), utf8str, sizeof(utf8str)) < 0)
{
RLOGE("format change error");
}
printf("gbk to utf8:%s\n", utf8str);
writeStringToParcel(p, (const char *)utf8str);//ussdString
}
else
{
printf("--------utf8:%s\n", srcstr);
writeStringToParcel(p, (const char *)srcstr);//ussdString
}
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int cancelPendingUssi(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 1)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx ussdString
int sendUSSD(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 2)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
writeStringToParcel(p, (const char *)argv[1]);//ussdString
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int cancelPendingUssd(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 1)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int getCLIR(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 1)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx clirMode
int setCLIR(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 2)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(1);
//0: "user subscription default value; 1:restrict CLI presentation; 2: allow CLI presentation
p.writeInt32(atoi(argv[1]));//clirMode
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int queryCLIP(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 1)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx cfReason serviceClass number
// mCi.queryCallForwardStatus(commandInterfaceCFReason,0,null,resp);
int queryCallForwardStatus(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 4)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
int cfReason = scToCallForwardReason(argv[1]);
RLOGD("queryCallForwardStatus() cfReason: %d", cfReason);
if(cfReason == -1) return -1;
p.writeInt32(2);
p.writeInt32(cfReason); //cfReason
p.writeInt32(siToServiceClass(argv[2])); //serviceClass
p.writeInt32(toaFromString(argv[3])); //number
writeStringToParcel(p, argv[3]);//number
p.writeInt32(0);
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx action cfReason serviceClass number timeSeconds
int setCallForward(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 6 )
{
RLOGD("the paremeters isn't enough!");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
int action = atoi(argv[1]); //status
int reason = scToCallForwardReason(argv[2]);
if(reason == -1) return -1;
char* number = argv[3];
int time = siToTime(argv[4]);
int serviceClass = siToServiceClass(argv[5]);
p.writeInt32(action); //action
p.writeInt32(reason); //cfReason
p.writeInt32(serviceClass); //serviceClass
p.writeInt32(toaFromString(number)); //number
writeStringToParcel(p, number);
p.writeInt32(time); //timeSeconds
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx serviceClass
int queryCallWaiting(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 2)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(1);
p.writeInt32(siToServiceClass(argv[1]));//serviceClass
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx enable serviceClass
int setCallWaiting(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 3)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(2);
p.writeInt32(atoi(argv[1])? 1 : 0);//enable
p.writeInt32(siToServiceClass(argv[2])); //serviceClass
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx facility oldPwd newPwd
int changeBarringPassword(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 4)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(3);
char* facility = scToBarringFacility(argv[1]);
if(facility == NULL) return -1;
writeStringToParcel(p, facility); //facility
writeStringToParcel(p, (const char *)argv[2]); //oldPwd
writeStringToParcel(p, (const char *)argv[3]); //newPwd
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
//xxx enable
int setSuppServiceNotifications(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 2)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(1);
p.writeInt32(atoi(argv[1])? 1 : 0);//enable
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int setCLIP(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 2)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(1);
p.writeInt32(atoi(argv[1])? 1 : 0);//enable
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int getCOLP(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 1)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int setCOLP(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 2)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(1);
p.writeInt32(atoi(argv[1])? 1 : 0);//enable
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int getCOLR(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 1)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
android::Parcel p;
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int queryFacilityLockForApp(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
if(argc != 4)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
char* facility = scToBarringFacility(argv[1]);
if(facility == NULL) return -1;
char *password = argv[2];
if(strcmp(password, "null") == 0){
password = "";
}
int serviceClassX = SERVICE_CLASS_NONE;
if (strcmp(facility, CB_FACILITY_BA_FD) == 0) {
serviceClassX = SERVICE_CLASS_VOICE + SERVICE_CLASS_DATA + SERVICE_CLASS_FAX;
} else if(strcmp(facility, CB_FACILITY_BA_SIM) == 0) {
serviceClassX = SERVICE_CLASS_VOICE + SERVICE_CLASS_DATA + SERVICE_CLASS_FAX;
} else {
serviceClassX = siToServiceClass(argv[3]);
}
char serviceclass[16] = {0};
sprintf(serviceclass, "%d", serviceClassX);
char* appId = "";
if (strcmp(facility, CB_FACILITY_BA_FD) == 0) {
appId = getAid(socket_id);
} else if(strcmp(facility, CB_FACILITY_BA_SIM) == 0) {
appId = getAid(socket_id);
}
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(4);
writeStringToParcel(p, facility);
writeStringToParcel(p, password);
writeStringToParcel(p, serviceclass);
writeStringToParcel(p, appId);
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
int setFacilityLockForApp(int argc, char **argv, RIL_SOCKET_ID socket_id, RequestInfo *pRI) {
RLOGD("setFacilityLockForApp %d: " , pRI->pCI->requestNumber);
if(argc != 5)
{
RLOGD("the peremeters numbers isn't right , so return");
return -1;
}
char* facility = scToBarringFacility(argv[1]);
if(facility == NULL) return -1;
char *password = argv[2];
if(strcmp(password, "null") == 0){
password = "";
}
int serviceClassX = SERVICE_CLASS_NONE;
if (strcmp(facility, CB_FACILITY_BA_FD) == 0) {
serviceClassX = SERVICE_CLASS_VOICE + SERVICE_CLASS_DATA + SERVICE_CLASS_FAX;
} else if(strcmp(facility, CB_FACILITY_BA_SIM) == 0) {
serviceClassX = SERVICE_CLASS_VOICE + SERVICE_CLASS_DATA + SERVICE_CLASS_FAX;
} else {
serviceClassX = siToServiceClass(argv[3]);
}
char serviceclass[16] = {0};
sprintf(serviceclass, "%d", serviceClassX);
char* appId = "";
if (strcmp(facility, CB_FACILITY_BA_FD) == 0) {
appId = getAid(socket_id);
} else if(strcmp(facility, CB_FACILITY_BA_SIM) == 0) {
appId = getAid(socket_id);
}
const char *lockStrings = argv[4];
android::Parcel p;
size_t pos = p.dataPosition();
p.writeInt32(5);
writeStringToParcel(p, facility);
writeStringToParcel(p, lockStrings);
writeStringToParcel(p, password);
writeStringToParcel(p, serviceclass);
writeStringToParcel(p, appId);
p.setDataPosition(pos);
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}