You Are Here:

Community: Blogs

Open Source Bluetooth PAN's Forum Nokia Blog

Symbian, Descriptors and Unicode

Carbider | 20 January, 2009 11:41

    While programming Bluetooth data transmission routines I've come across an encoding issue at Symbian. The task was to send and receive Unicode strings encoded in UTF-16. The data was moved by RSocket class.

The thing is, the RSocket's read and write methods are taking the 8 bit descriptors only (representing the binary data), so we need to convert the 8 bit descriptors to 16 bit and vice versa. 
For example, we need to receive some UTF-16 string in Russian language from the server and display it on screen.

Some documents here suggest several solutions on converting descriptors, but they don't work as needed. Let me explain why.

The two common methods of conversion are:

1. To use Copy() method of first the descriptor to copy contents of the second one.

Example:

RBuf8  buf8     ;
RBuf16 buf16    ;

buf16.Copy(buf8);

As a result, the contents of buf8 descriptor would not be simply copied to buf16, but each character would be expanded to 16 bits.
So the string “Hello” would become something like “_H_E_L_L_O” after expanding.




Image 1 – Example of how the Copy() method works, and what we actually need.

On the contrary, when converting the 16 bit descriptor to an 8 bit descriptor, the contents of the first would be collapsed. 

That is a behavior of Copy() method.

2. The second method is to use a CnvUtfConverter class provided in Symbian.

Example:

HBufC8 *heap8;
HBufC  *heap16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L(*heap8);

This method will convert between the Unicode and UTF-8. That is again is not what I needed. What I need is the conversion between the descriptor classes themselves but not transforming their contents, that should stay without any change.

Solving

So to read the Unicode string presented in binary format from socket and display it on screen, we need to convert the descriptor's body (8 bit descriptor to 16 bit descriptor) but not the descriptor's contents.

Here is a method on how can it be done.
To pass the descriptor's contents from the descriptor of one type to another, we have to copy contents somehow. I chose the memcpy() function. If you find a better (or safer) way, please submit it here. 
Example:

Copy the contents of 8 bit descriptor to the 16 bit one.
(without memory allocation routines)

TBuf8       sourceBuf8        ;
TBuf16      destBuf16         ;

TInt len = sourceBuf8.Length();
aOutDest.FillZ(len/2 ); // necessary to set the size memcpy((TAny *)destBuf16.Ptr(), (TAny *)sourceBuf8.Ptr(), len);



This works smoothly for S60 3rd FP1, both emulator and Nokia E90 device.

I wrote the CBinaryConverter class that has two methods, doing these operations. It is attached to this post.

Example of using CBinaryConverter class:



RBuf8 source                      ;
RBuf   dest                       ;  // the same as Rbuf16
TInt destLength                   ;
source.Create(100                );

// Receive the 8 bit descriptor from socket that contains 16 bit data iActiveSocket->RecvOneOrMore(source, 0, iStatus, iLen );
destLength = source.Length() / 2 ; // 16 bit chars instead of 8 bit
dest.CleanupClosePushL() ; // to Cleanup Stack dest.Create( destLength );
//Conversion CBinaryConverter::copy8BitInto16BitDescriptorL(source, dest );
// Show the note CAknInformationNote *iInfNote ; iInfNote = new (ELeave) CAknInformationNote(); iInfNote->ExecuteLD(dest );
CleanupStack::PopAndDestroy(&dest); // Pop RBuf from the Cleanup Stack


Screenshot of the application, that controls Juke Box holding songs in English and Russian languages over Bluetooth:




Download the source code

Download zip package:
BinaryConverter_class.zip

Or view directly:

BinaryConverter.cpp
BinaryConverter.h

 




--
Cheers
Konstantine



PAN service advertise

Carbider | 28 May, 2008 14:47


It is interesting the PAN (Bluetooth Personal Area Networking) profile is listed at Symbian 9.2 abilities.
The PAN overview is here:
...symbian.com/developer/techlib/v9.2docs/...

And a small API mention is here:
...symbian.com/developer/techlib/v9.2docs/...

Despite the fact that there is no completely ready PAN API in S60 3rd there are some type definitions and constants related to the deal. They are defined at btsdp.h header file here:
...symbian.com/developer/techlib/v9.2docs/...

Here are some constants that seem to be tempting for my Bluetooth inquisitive mind:

Listing - 1
/** PAN Service Class UUID */
static const TInt KPanUUUID = 0x1115;
/** PAN NAP Service Class UUID */
static const TInt KPanNapUUID = 0x1116;
/** PAN GN Service Class UUID */
static const TInt KPanGnUUID = 0x1117;


These values represent identifiers of Bluetooth(c) services that could be advertised by device.

There is a Chat example that advertises the Serial Port service. I decided to try one's luck with PAN.

const TInt KServiceClass = 0x1101;    //  SerialPort

Chat example supplies the service's identifier constant by returning this value from function below:

Listing - 2
TInt CChatServiceAdvertiser::ServiceClass()
{
    return KServiceClass;
}

The KServiceClass constant is assigned to '0x1101' by default. I've changed the function to this manner:

Listing - 3
TInt CChatServiceAdvertiser::ServiceClass(TInt aAttemptNumber)
{
    switch(aAttemptNumber) {
     case 0 :
        return 0x1115; // PAN
        break;
     case 1 :
     return 0x1116; // PAN NAP
     break;
     case 2 :
     return 0x1117; // PAN GN
     break;
    }
}


This gives me a possibility to supply the AttemptNumber parameter to the function - so to test all 3 service classes by turns.

In the similar manner I had rewritten the function that returns the service's symbolic name.

Listing - 4
const TDesC& CChatServiceAdvertiser::ServiceName(TInt aAttemptNumber)
{
 switch(aAttemptNumber) {
 
  case 0 :
     return _L("PAN"    );  //  PAN
     break;
  case 1 :
     return _L("PAN NAP");  //  PAN NAP
     break;
  case 2 :
     return _L("PAN GN" );  //  PAN GN
     break;
 
     
 }
}

Each time I've started the chat server I’ve outputted the qualifying message in this way:

iLog.LogL( _L("Attempt#"), iAttemptNumber );


After building the application under Phone release (GCCE) I had signed it myself and sent to my device.

As a Contributor of the Month I have got one. It's a Nokia N95 8GB.
With that one I can test a lot. It really helps in development. And also that multimedia computer is cool one ;)

Then I started the app on the phone and turned on the PAN search service on the WinXP SP2 machine.
However after all three service classes were advertised one by one, the XP machine did not detect any.

Lost in the dark

Carbider | 21 February, 2008 12:32

As you know, I've worked a lot to figure out a way of how to realize the BNEP protocol on Symbian platform.

The simple idea of catching and processing all the TCP stream with help of IP hook is impossible until purchase non-publick API.
Also, the idea to create a networking interface or serial protocol modules (this blog entries:attempt-to-create-a-csy-module, serial-protocol-modules, symbian-networking-interface) failed to due to lack of examples.

Now, I'm moving like in a dark. And can't find a way to realize the BNEP.
Boss said me to try for 2 more weeks, to find out.
I do not see much sense if this blog ends with purchasing a non-publick API.

If anyone can provide an idea, let me know.

 
1 2 3 4 5 6 7 8  Next»
 

Rate This

 
 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia 
User Rating: qfnZuserE5FratingQNx1E2E0000X