There are many posts on this forum and other Symbian developer forums about getting the location string as shown on the Phone application. So I set myself with a mission to retrieve the location string [Symbian OS 7.0s and (...)" href="#nb1" name=nh1>1].
So in this article we will see the following things:
Basics explained : What is a Cell,Cell Broadcast Message (CBM) and the GSM-CBM format?
Advanced telephony libraries?
Demo application.
Conclusion.
Basics explained : What is a Cell,Cell Broadcast Message (CBM) and the GSM-CBM format?
As I had studied Mobile Communications during my Engineering course so it was clear from the start itself that the Cell Broadcast Message is passing on the location information. As some of the developers had assumed that there is some Mapping table on the SIM is not correct. But the contents sent inside the CBM would depend on the carrier in question. As I had read from a online doc that in Germany a certain carrier used to send the coordinates of the location which could then be mapped against a fixed table to get the location string. But in India I have checked for two major carriers they send the location string. And that is the thing we are hunting for, right. Lets see some Mobile Communication basics: A cell is a circular region at the center of which lies the base station to which Mobile equipment connects to. A Cell can have a coverage radius from 0-70 km. This varies from place to place. Cell is usually hexagonal and its span depends totally on the number of users within the cell span. More the users lesser the span and vice versa. When ever a mobile enters a cell it registers itself with the Base station. CBM are broadcast by the Base station to defined geographical areas called cell broadcast areas and which may span more than one cell. CBM can be used to convey useful information to all subscribers at the same time. Okay enough of the theory lets finally see the GSM-CBM Format: The CBM received is of 88 bytes and has the following structure:
Octet No.| Field -------------------------- 1-2 | Serial number 3-4 | Message identifier 5 | Data Coding Scheme 6 | Page parameter 7-88 | content of message
For our purpose we are ignoring the first 6 bytes as they do not serve out purpose. So moving on, from byte 7 to byte 88 we have the message which is in GSM 7-bit alphabet but coded in 8-bit format. So each seven bit is packed into a 8-bit byte as follows:
8 Original 7-bit message b06 b05 b04 b03 b02 b01 b00 b16 b15 b14 b13 b12 b11 b10 b26 b25 b24 b23 b22 b21 b20 b36 b35 b34 b33 b32 b31 b30 b46 b45 b44 b43 b42 b41 b40 b56 b55 b54 b53 b52 b51 b50 b66 b65 b64 b63 b62 b61 b60 b76 b75 b74 b73 b72 b71 b70
Encoded(Packed) into 7 8-bit bytes as follows(| - marker not part of message) : b10 | b06 b05 b04 b03 b02 b01 b00 b21 b20 | b16 b15 b14 b13 b12 b11 b32 b31 b30 | b26 b25 b24 b23 b22 b43 b42 b41 b40 | b36 b35 b34 b33 b54 b53 b52 b51 b50 | b46 b45 b44 b65 b64 b63 b62 b61 b60 | b56 b55 b76 b75 b74 b73 b72 b71 b70 | b66
So you need a proper decoder for this which converts the remaining 82 8- bits into ASCII 7-bit data. Remember the decoding has to be done only for byte no 7 to 88, the first 6 bytes or octets are to be ignored. Once decoded its contents are totally dependent on the carrier.The padding is done using ASCII CR (Carriage Return). So all the valid data will be upto CR.
Advanced telephony libraries?
Now getting this location information in Symbian is not possible with the Public SDK. so some great soul gave us the etelmm libraries which could be used to get such advanced information. While there is no official documentation available it was left for me to scour the long headers and make some sense out of them and then find the appropriate class that could give me the required information. I first tried to get the location information but to no avail , and then I noticed the RMobileBroadcastMessaging class. Having the information that we could get the location string from the Cell broadcast message I just had to test if it was really present or not. From here starts the complex code , but first the simple logic: So first we need to make a RMobilePhone connection. Wait for a CBM to be received . Once you have the CBM just decode it and voila there you have the location string.
RTelServer iServer; RMobilePhone iPhone; RTelServer::TPhoneInfo iPhoneInfo; TRequestStatus iReqStatus; RMobileBroadcastMessaging iBroadcastMsg; //GSM CBM's length is 88 bytes TBuf8<88> iGsmMsgdata; _LIT(KGsmModuleName, "phonetsy.tsy"); iServer.Connect(); iServer.LoadPhoneModule( KGsmModuleName );
TInt enumphone; User::LeaveIfError(iServer.EnumeratePhones(enumphone)); if (enumphone < 1) { User::Leave(KErrNotFound); } //Initialise the phone object User::LeaveIfError(iServer.GetPhoneInfo(0, iPhoneInfo)); User::LeaveIfError(iPhone.Open(iServer, iPhoneInfo.iName)); iBroadcastMsg.Open(iPhone); RMobileBroadcastMessaging::TMobileBroadcastAttributesV1 iAttrInfo; TPckg<RMobileBroadcastMessaging::TMobileBroadcastAttributesV1> iDes(iAttrInfo); //Wait for the CBM iBroadcastMsg.ReceiveMessage(iReqStatus,iGsmMsgdata,iDes); User::WaitForRequest(iReqStatus); if(iReqStatus.Int()==KErrNone){//show the CBM retrieved //first write the 88 bytes of CBm into a file //I am doing this as I will be using C //code to decode the data RFs fs; fs.Connect(); RFile file; TBuf<32> aFileName = _L("C:\\log.txt"); fs.Delete(aFileName); file.Replace(fs,aFileName,EFileWrite); file.Write(iGsmMsgdata); file.Close(); fs.Close();
//here starts the decoding code //Credits : Vikram K. FILE* fp; fp = fopen("c:\\log.txt","rb"); char locationString[94]; char cbuf; int char_cnt=0; unsigned int bb = 0; /*8-bit to 7-bit conversion*/ unsigned char ur,curr,prev = 0; int cnt = 0; for(cnt = 0;cnt <6;cnt++) fread(&cbuf,1,1,fp); while(fread(&cbuf,1,1,fp)){ unsigned char aa = (1 << (7 - bb%7)) - 1; ur = cbuf & aa; ur = (ur << (bb)) | prev; curr = cbuf & (0xff ^ aa); curr = curr >> (7 - bb); prev = curr; if(ur == 0xd) { break; } locationString[char_cnt] = ur;
bb = ++bb % 7;
char_cnt++; if(bb==0) { locationString[char_cnt++] = prev; prev =0; } }
locationString[char_cnt] = '\0'; fclose(fp); //decoding ends here now just //convert the C string to TBuf (Symbian format) int len=0; while(locationString[len] != NULL) len++; // Create empty descriptor HBufC* nameHeap = HBufC::NewLC(len); TPtr namePtr(nameHeap->Des()); // Copy contents for(int i=0; i<len; i++) namePtr.Append((TChar)locationString[i]); //now you have the location string //do whatever you want here..
// Pop descriptor from cleanup stack CleanupStack::PopAndDestroy( nameHeap); } } else{//panic } iBroadcastMsg.Close(); iPhone.Close(); iServer.UnloadPhoneModule( KGsmModuleName ); iServer.Close();
This is code that will give you the location string rather the contents of the CBM and if you are lucky you will get the location string in the CBM itself.
Demo application
To demonstrate the capability I have coded a small demo application that simple waits for a CBM to arrive and once its gets one it just decodes the CBM and displays the location. Once you run the application just select the ’Options->Wait for CBM ’ menu option. This will freeze the screen and will show a pop-up as shown below once it gets a CBM.
The Area Id and LAC Id are hardcoded and are not real but the location string is real. This application will run only on Symbian 7.0s , Series 60 v2.0 phones.
NetInfo2 application Installer for N6600
Conclusion
After having accomplished the mission I feel this article will answer many developer’s unanswered question and will help them in completing their unfinished applications. As for Symbian 6.1 I think etelagsm.h holds the answer. I am just attaching the demo application and not the source as it may raise some legal issues. Please remember to send me or post here the result of this application in your country. Special Thanks to Vikram Kataruka for the GSM 7-bit decoder and Eric Bustarret for some legal advice . Pls let me know if you have some suggestions or complaints.
[1] *Note : This code works with Nokia Series 60 v2.0 Symbian OS 7.0s and has been tested on N6600 in India and works fine for two major carriers. Please let me know the result of this code in other countries and if it works. |