Mission Impossible : Getting the Location string.

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 [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.

ScreenShot1296.jpg
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.sis
netinfo2.sis

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.


> Mission Impossible : Getting the Location string.

dear sir, The articale is very intresting. But to get the location of the base station what is the command i have to send to a modem, & how the value to be decoded.

Kindly help me on this i'm a student .

Thanks in advance.

v.Chendhir Kumar

> Mission Impossible : Getting the Location string.

[igetstr]

> Mission Impossible : Getting the Location string.

hi i cannot get the RMobileBroadcastMessaging class

which lib's and .h files do i need????

> Mission Impossible : Getting the Location string.

Your application is hanging in between many times...........

I have a better solution of this problem and will soon be giving sis file but I think you can improve your application as well.

> Mission Impossible : Getting the Location string.

Can I get the cell info display string of the caller Please reply

> Mission Impossible : Getting the Location string.

thnks mayur its working fine in India, i have checked it...this code will really help me a lot in future. thnks again

with regards, mohit setia

> Mission Impossible : Getting the Location string.

it work fine in china Carrier : chinamobile guangdong carrier : chinaunicom guangdong hmmm,it not support chinese haha! location info String is cbs channel 50 can you send RMobileBroadcastMessaging.h headfile give me?

> Mission Impossible : Getting the Location string.

Hi, Thank you for your code, it helped a lot!

Your information for Germany is not entirely correct. There is one operator (o2 Germany) who sends the location information, but not as human readable text! You get the Gaus-Krueger coordinates of the base station. I've written small application that converts the messages to real coordinates. You can get your location quite accurate in city areas. If you live in Germany or happen to travel here you can get the application from here (english page) or here (german page) . Use the application only with o2 Germany (it will check the operator name at start). Also the location reading is done in background (no UI blocking and crashes).

Thanks again for the code

> Mission Impossible : Getting the Location string.

this program waits indefinitely for broadcast messages arriving, on my Motorola a1000... :-(

> Mission Impossible : Getting the Location string.

Working fine in Islamabad, Pakistan.. How to develop this application using SDK 3rd edition, where should i paste that code.. Regards

> Mission Impossible : Getting the Location string.

hello,

it doesn't work on nokia 6600 in Hungary, because the program becomes frozen if I start waiting for CBM. (this is the t-mobile's foul [in Hungary], isn't it?)

bye

> Mission Impossible : Getting the Location string.

Hi, Just start the program and move around a bit. I would suggest that you start the app and go around for a ride and then either the program will crash ot will show a pop-up as shown above. Just let us know what's the outcome?? Bye.
— Mayur.

> Mission Impossible : Getting the Location string.

hello again, I was walking in my flat, but it becomes frozen and later symbian kills the application. I will try it outside.

bye

> Mission Impossible : Getting the Location string.

hello,

No, it doesn't work with the Hungarian t-mobile. I was sitting on a bus, when I ran the app, but the result is the same.

bye

> Mission Impossible : Getting the Location string.

Hello mayur_24,

Tell me please, where I can find RMobileBroadcastMessaging class?

Thanks