#include #include "RilMonitor.h" #include "RilExceptions.h" #include "debug.h" #include "stringutils.h" #include "args.h" #include "pkfuncs.h" // PROCESSOR_INFO, KernelIoControl, IOCTL_PROCESSOR_INFORMATION // this program makes test calls via ril with all known cbst parameters, to test what bearer types are supported // on a phone // for event handler #include #include "RilStructDecoder.h" #include "RilEventsSigQuality.h" #include "RilEventsCallState.h" #include "RilEventsNetwork.h" #include "RilReadWrite.h" // MISC::SIMSTATUSCHANGED // PHONEBOOK::PHONEBOOKSTORAGECHANGED // RADIOSTATE::RADIOPRESENCECHANGED // NOTE: this program needs cryptophone running, for the rilgsm patch // or do: ( for diamond/nld 1.93 rom ) // psetmem -4 0x7825f264 0xE1A00000 0xE1A00000 0xE1A00000 0xE1A00000 0xE1A00000 0xE1A00000 // // (herald 5.4.405.1 ) // psetmem -4 -n device.exe 0x01606EE4 0xE1A00000 0xE1A00000 0xE1A00000 0xE1A00000 0xE1A00000 0xE1A00000 // // TODO: problem is that sometimes rilphone.dll misses a 'disconnected' event on the atcmd layer. #define RIL_NOTIFY_LOCATIONINFO (0x00000008 | RIL_NCLASS_NETWORK) bool g_flood= false; DWORD g_delay= 2000; DWORD g_ntests= 1; DWORD g_do_i_test= false; int cbstnametypes[]= {0,1,4}; #define N_CBSTNAMETYPES (sizeof(cbstnametypes)/sizeof(*cbstnametypes)) int cbstcetypes[]= {0,1}; #define N_CBSTCETYPES (sizeof(cbstcetypes)/sizeof(*cbstcetypes)) int cbstsettings[][3]= { { 0,0,1 }, // auto, async, non-transparent { 12,0,0 }, // 9600 bps V.34 transparent { 12,0,1 }, // 9600 bps V.34 { 14,0,0 }, // 14400 bps V.34 transparent { 14,0,1 }, // 14400 bps V.34 { 16,0,1 }, // 28800 bps V.34 { 17,0,1 }, // 33600 bps V.34 { 39,0,1 }, // 9600 bps V.120 { 43,0,1 }, // 14400 bps V.120 { 48,0,1 }, // 28800 bps V.120 { 51,0,1 }, // 56000 bps V.120 { 75,0,1 }, // 14400 bps V.110 { 80,0,1 }, // 28800 bps V.110 { 81,0,1 }, // 38400 bps V.110 { 83,0,1 }, // 56000 bps V.110 { 83,4,1 }, // 56000 bps V.110, async RDI { 84,0,1 }, // 64000 bps X.31 flag stuffing- FTM { 6,0,0 }, // 4800 bps V.32 transparent { 6,0,1 }, // 4800 bps V.32 { 70,0,0 }, // 4800 bps V.110 transparent { 70,0,1 }, // 4800 bps V.110 { 7,0,0 }, // 9600 bps V.32 transparent { 7,0,1 }, // 9600 bps V.32 { 71,0,0 }, // 9600 bps V.110 transparent { 71,0,1 }, // 9600 bps V.110 { 116,1,0 }, // 64000 bps bit transparent, sync, transparent { 134,1,0 }, // 64000 bps multimedia, sync, transparent }; #define N_CBSTSETTINGS (sizeof(cbstsettings)/sizeof(*cbstsettings)) void RegSetIntvalue(HKEY hRoot, const char*path, const char*key, int value) { HKEY hKey; LONG res= RegOpenKeyEx(hRoot, ToTString(path).c_str(), 0, KEY_ALL_ACCESS, &hKey); if (res!=ERROR_SUCCESS) throw "regopen"; res= RegSetValueEx(hKey, ToTString(key).c_str(), NULL, REG_DWORD, reinterpret_cast(&value), sizeof(int)); if (res!=ERROR_SUCCESS) throw "regsetval"; res= RegCloseKey(hKey); if (res!=ERROR_SUCCESS) throw "regsetval"; } std::string getoemname() { WCHAR oeminfo[256]; if (SystemParametersInfo(SPI_GETOEMINFO, 256, oeminfo, 0)) return ToString(oeminfo); return ""; } void getprocessorinfo(std::string& processor, std::string& core) { PROCESSOR_INFO pi; DWORD nReturned; if (!KernelIoControl(IOCTL_PROCESSOR_INFORMATION, NULL, 0, &pi, sizeof(pi), &nReturned)) { error("IOCTL_PROCESSOR_INFORMATION"); } core= ToString(pi.szProcessCore); processor= ToString(pi.szProcessorName); } #define CAPS_HTC_QUALCOMM 1 #define CAPS_HTC_OMAP 2 #define CAPS_HTC 4 #define CAPS_SAMSUNG 8 int g_caps; void determine_system_caps() { std::string oemname= getoemname(); std::string processor; std::string core; getprocessorinfo(processor, core); debug("oem=%s, proc=%s, core=%s\n", oemname.c_str(), processor.c_str(), core.c_str()); if (oemname=="SGH-i900") g_caps=CAPS_SAMSUNG; else if (oemname=="HTC Touch Pro T7272") g_caps=CAPS_HTC|CAPS_HTC_QUALCOMM; else if (oemname=="HTC Touch Diamond P3700") g_caps=CAPS_HTC|CAPS_HTC_QUALCOMM; else if (oemname=="Kaiser") g_caps=CAPS_HTC|CAPS_HTC_QUALCOMM; else if (oemname=="HERA10000") g_caps=CAPS_HTC|CAPS_HTC_OMAP; else if (oemname.find("HTC")!=oemname.npos) { g_caps=CAPS_HTC; if (processor.find("OMAP")!=processor.npos) g_caps|=CAPS_HTC_OMAP; if (core.find("MSM")!=processor.npos) g_caps|=CAPS_HTC_QUALCOMM; } debug("-> caps=%x\n", g_caps); } bool hascaps(int caps) { if (g_caps&caps) return true; debug("missing caps: %d\n", caps); return false; } void setphonecbst(int speed, int name, int ce) { if (!hascaps(CAPS_HTC)) return; RegSetIntvalue(HKEY_CURRENT_USER, "ControlPanel\\PhoneExtendFunction", "CSDISDNEnable", 1); RegSetIntvalue(HKEY_CURRENT_USER, "ControlPanel\\PhoneExtendFunction", "CBSTSpeed", speed); RegSetIntvalue(HKEY_CURRENT_USER, "ControlPanel\\PhoneExtendFunction", "CBSTName", name); RegSetIntvalue(HKEY_CURRENT_USER, "ControlPanel\\PhoneExtendFunction", "CBSTCe", ce); } // used by uni_at.exe to send at commands std::string sendatcommand(rilmonitor& m, const std::string& atcmd) { if (!hascaps(CAPS_HTC_QUALCOMM)) return ""; ByteVector response; ByteVector request(atcmd.size()+5); request[0]= 0x33; memcpy(&request[4], atcmd.c_str(), atcmd.size()); requesthandler_ptr rl= m.DevSpecific(request, response); rl->wait(); if (rl->errorcode() || rl->lineerror()) debug("%s : ERROR %08lx / %08lx\n", atcmd.c_str(), rl->errorcode(), rl->lineerror()); else { return std::string(&response[0],&response[response.size()]); } return ""; } bool testcbst(rilmonitor& m, int speed, int name, int ce) { try { std::string response= sendatcommand(m, stringformat("AT+CBST=%d,%d,%d\r", speed, name, ce)); return !response.empty() && (response[0]=='0' || response[0]=='O'/*OK*/); } catch(ril_error& e) { debug("at+cbst-rilerr: %08lx: %s\n", e.err, e.name.c_str()); } catch(ril_structsize_error& e) { debug("at+cbst-rilsize: got %d, expected %d\n", e.got, e.expect); } catch(...) { debug("at+cbst-unknown exception\n"); } return false; } bool enablev80(rilmonitor& m) { try { sendatcommand(m, "AT+ES=6,,8\r"); return true; } catch(ril_error& e) { debug("enablev80-rilerr: %08lx: %s\n", e.err, e.name.c_str()); } catch(ril_structsize_error& e) { debug("enablev80-rilsize: got %d, expected %d\n", e.got, e.expect); } catch(...) { debug("enablev80-unknown exception\n"); } return false; } void transfertestdata(rilmonitor& m) { const uint8_t *teststring= (const uint8_t*)"00ghijklmnopqrst01ghijklmnopqrst02ghijklmnopqrst03ghijklmnopqrst04ghijklmnopqrst05ghijklmnopqrst06ghijklmnopqrst07ghijklmnopqrst08ghijklmnopqrst09ghijklmnopqrst0aghijklmnopqrst0bghijklmnopqrst0cghijklmnopqrst0dghijklmnopqrst0eghijklmnopqrst0fghijklmnopqrst"; // ByteVector bv; // for (int i=0 ; i<256 ; i++) bv.push_back(i); ByteQueue qin(1024, "rilread"); RilReader r(m,qin); ByteQueue qout(1024, "rilwrite"); RilWriter w(m,qout); qout.writevec(ByteVector(teststring, teststring+256)); Sleep(40000); qin.stop(); qout.stop(); r.stop(); w.stop(); } void transferflooddata(rilmonitor& m) { ByteQueue qin(1024, "rilread"); RilReader r(m,qin); RilFlood w(m); DWORD t0= GetTickCount(); while (GetTickCount()-t0 < 60000) { ByteVector bv(256); qin.read(&bv[0], 1, 256); } qin.stop(); r.stop(); w.stop(); } void handleincoming(rilmonitor& m, callstate_waitvar& state) { try { requesthandler_ptr rq= m.Answer(); debugt("answering, state=%d\n", state.get()); rq->wait(); if (rq->errorcode() || rq->lineerror()) { debug("answer : ERROR: %08lx / %08lx\n", rq->errorcode(), rq->lineerror()); return; } debugt("answer ok, state=%d\n", state.get()); int st= state.wait_not_equal(CALLSTATE_RING, 20000); if (st==CALLSTATE_CONNECTED) { if (g_flood) transferflooddata(m); else transfertestdata(m); requesthandler_ptr rh= m.Hangup(); rh->wait(); if (rh->errorcode() || rh->lineerror()) debug("hangup error: %08lx / %08lx\n", rh->errorcode(), rh->lineerror()); debugt("hangup ok\n"); state.wait_equal(CALLSTATE_DISCONNECTED); } } catch(ril_error& e) { debug("answer: %08lx: %s\n", e.err, e.name.c_str()); } catch(ril_structsize_error& e) { debug("answer: got %d, expected %d\n", e.got, e.expect); } catch(...) { debug("answer: unknown exception\n"); } } void makedatacall(rilmonitor& m, callstate_waitvar& state, const std::string& number, bool bPresentId) { try { state.set(CALLSTATE_CONNECTING); requesthandler_ptr rd= m.Dial(number, RIL_CALLTYPE_DATA, bPresentId ? RIL_DIALOPT_PRESENTID : 0); debugt("dialing, state=%d\n", state.get()); rd->wait(); if (rd->errorcode() || rd->lineerror()) { debug("dial error: %08lx / %08lx\n", rd->errorcode(), rd->lineerror()); return; } debugt("dial ok, state=%d\n", state.get()); int st= state.wait_not_equal(CALLSTATE_CONNECTING, 20000); if (st==CALLSTATE_CONNECTED) { debug("datacall connected, testing data transfer\n"); if (g_flood) transferflooddata(m); else transfertestdata(m); requesthandler_ptr rh= m.Hangup(); rh->wait(); if (rh->errorcode() || rh->lineerror()) debug("hangup error: %08lx / %08lx\n", rh->errorcode(), rh->lineerror()); debugt("hangup ok\n"); state.wait_equal(CALLSTATE_DISCONNECTED); } else if (st==CALLSTATE_INCOMING) { // for video calls, it is like you receive a call after dialing. debug("datacall incoming: answering\n"); handleincoming(m, state); } else { debug("datacall failed: st=%d\n\n", st); } } catch(ril_error& e) { debug("makecall-rilerr: %08lx: %s\n", e.err, e.name.c_str()); } catch(ril_structsize_error& e) { debug("makecall-rilsize: got %d, expected %d\n", e.got, e.expect); } catch(...) { debug("makecall-unknown exception\n"); } } void runtest(rilmonitor& m, callstate_waitvar& state, int speed, int name, int ce, const std::string& num) { // for non-qualcomm dial all. if (!hascaps(CAPS_HTC_QUALCOMM) || testcbst(m, speed, name, ce)) { if (!num.empty()) { debugt("testing %3d,%d,%d\n", speed, name, ce); setphonecbst(speed, name, ce); if (g_do_i_test) { for (int i=0 ; i