Index
With the extensive development of the mobile phone industry, our mobile phones are becoming more powerful than before. Today, mobile phones can process pictures, sound, and even video. We can get pictures from a phone's camera, or download them from a PC or from a web site. I have two phones, a Siemens CXV65 and a Nokia 6021. It is boring that I must install two separate software when I want to transfer a picture to them. And this really takes a lot of my disk space and slows down my machine.
Though we can buy commercial software to do this, I was wondering if it was possible to develop a software by myself? That was a surprising idea, and I did finish it. Now I will tell you how I did it, in a top-down perspective. In this article, you will learn what is OBEX, FBUS, and a plug-in scheme. I hope the code or data examples and the comments in the source code will give you a clear picture. Hope you like this article!
Before I started this program, I did a lot of work on SMS (Short Message Service) using Visual Studio 2003. It's hard to find a really stable and extensible serial port class under .NET 1.1, and because of this, a lot of work failed at this period. But today, both .NET 2.0 and .NET 2.0 Compact Framework provide us a pretty good serial port class under the System.IO.Ports
namespace, which is stable, extensible, and easy to use. So now, we can write our own serial port programs much easier than before.
Both of my phones are serial port based phones which provide a data cable plug-in. The Siemens CXV65 phone has two kinds of data cables, a 540 data cable and a 510 data cable. I have both of them. When the 540 data cable is plugged, my PC will find a Siemens Modem using COM3. And the 510 data cable is just a PL2303 USB to the Serial Port bridge. Nokia phones have two kinds of cables too, DKU-2 and DKU-5 data cables. My Nokia 6021 uses the DKU-5 data cable which is also just a PL2303 bridge.
As you will see later, Siemens phones use the OBEX (Object Exchange) protocol to handle file transferring, and most Nokia phones use a protocol called the FBUS protocol, and some use the MBUS protocol. OBEX protocol is documented in detail, but it's hard to find FBUS documentation. I'll introduce both OBEX and FBUS later.
Let's start!
|
The complete solution contains seven projects:
- FileTransferCodeDemo
Demo project main form.
- SDK
Software Development Kit for my plug-ins, containing:
- An OBEX client protocol (OBEX folder)
Provides major features including connect, disconnect, and file transfer.
- Plug-in interface (IPhonePlugIn.vb)
- Serial port connection monitor (Monitor.vb)
Auto detect a phone by this program.
- Plug-in discovery and use service (PlugInSerivce.vb).
- Plug-ins
Other projects are all plug-ins. Plug-ins are mainly based on the service the SDK provides. All plug-ins are used for demo only, and they provide only one way transfer from a PC to a phone. SonyEricsson, Siemens CX6C, and Moto are based on the OBEX protocol. NokiaS40 is based on the FBUS protocol. Samsung is based on its own AT based protocol.
Caution:
- NokiaS40 FBUS protocol has only a core technology on PC to phone transferring; no error report, no fail notice. If it fails, it even creates a dead file on your phone, and you can't delete it!!!
- All plug-ins should be used at your own risk!!!
I will focus on the SDK project and the plug-ins. To get these projects to work together, please look into the FileTransferCodeDemo project.
|
As mobile phones from different companies are different from each other, we can't write a single program to support all the phones. If we could, it will surely be a large project and will lack extensibility. We must find a way to make our life easier. A plug-in scheme will satisfy such needs:
- It's flexible. We can write a main program, and the only work left is to just write plug-ins and copy their DLL files.
- It's easy to manage. When we find bugs, we simply modify and test individual plug-ins without touching other plug-ins and the main program.
- It's easy to use. If I have one phone, I can copy only one of the DLLs.
A plug-in interface is an interface that defines the major common functions we will use in our plug-ins. All plug-ins will implement this interface. Later on, my plug-in service will find all the classes in the DLLs that implement this interface. My interface is shown below:
Plug-in services provide the ability to search for the DLLs to implement a certain interface. .NET provides us with the System.Reflection
namespace to do reflection from a DLL. The FindPlugins
function finds all DLLs, and then the ExamineAssembly()
function uses reflection to examine the DLLs. The CreateInstance()
function is used to create an object instance of the plug-in. Please see the code for details. I thank the author for writing these segments.
I wrote a SelectPlugin()
function. This function checks a mobile phone's model ID and then compares it with the <Plug-in>.SupportModelID()
string. If they match, the function will return a plug-in number to indicate which plug-in to use.
It's easy to check the model ID of a phone. You can simply send an AT command called "AT+CGMM" to the serial port and then compare the return string.
Here is the code segment to demonstrate the usage of my plug-in scheme:
Dim ap As PluginServices.AvailablePlugin()
ap = PluginServices.FindPlugins(Application.StartupPath, _
"Dreamworld.FileTransfer.SDK.IPhonePlugIn")
Dim pluginToUse As Integer = _
PluginServices.SelectPlugin(phoneID, ap)
Dim phone As IPhonePlugIn = _
CType(PluginServices.CreateInstance(ap(pluginToUse)), _
IPhonePlugIn)
Here, I will only show you some basic serial port operations used in my code. For more serial port examples, please see MSDN documents.
First, you must import the System.IO.Ports
namespace to your project. Then you create a new instance of SerialPort
; here, we will call it mPort
.
Then you must do some settings to the serial port.
mPort.PortName = "COMx"
mPort.BaudRate = 115200
mPort.DtrEnable = True
mPort.RtsEnable = True
mPort.NewLine = Chr(13)
mPort.Open()
At this point, you can simply use mPort.Write()
or mPort.Read()
to send and receive binary data. To send AT commands, you can use mPort.WriteLine()
and mPort.ReadLine()
instead.
Here is a simple function to send and receive AT commands.
Function SendAT(ByVal cmd As String) As String
mPort.NewLine = Chr(13)
mPort.WriteLine(cmd)
mATTimeOut = 1000
Dim response As New Text.StringBuilder
Dim start As Date = Now
Do
Thread.Sleep(10)
Dim rsp As String = mPort.ReadExisting()
response.Append(rsp)
If Now.Subtract(start).TotalMilliseconds > _
mATTimeOut Then
Throw New TimeoutException("AT TimeOut")
If response.ToString.Contains("OK") Or _
response.ToString.Contains("ERROR") Then
Exit Do
Loop
Return response.ToString
End Function
For more details, please see my program and also MSDN documents.
I found a very powerful tool called HHD Serial Monitor for monitoring and analyzing data transfer. It can monitor the data sent and received by your serial port. The newest version can be found here. In this article, I use the version 3.22 because I found that I couldn't monitor a modem in the 4.0 version.
OBEX is an abbreviation of Object Exchange, which is a top level protocol of the IrDA or Bluetooth technology. OBEX is widely used on mobile devices such as PDAs and mobile phones. Both my phones support OBEX. For Siemens, SonyEricsson, and Motorola, OBEX is easy to use, but Nokia phones use OBEX over FBUS which is hard to use.
Please refer to the IrOBEX protocol for more details on this subject.
These examples are from my previous article. I use a serial monitor to monitor the data. A PC is the client and a Siemens M55 is the server.
Note:
Gray color is used for the explanations and yellow color for real data.
- Connect, Disconnect
Data transfer:
- Send a file to \Sound\1.mid, 313 bytes.
Siemens has a maximum package length of 474 bytes. So this file can fill in a package.
Brief process: Connection->Switch to root->Switch to Sound folder->Put->…
Exact process: (Ignore connection portion)
- Send a file to \Pictures\102725.jpg, 5314 bytes.
Brief process: Connection->Switch to root->Switch to \Pictures folder->Put->…
Exact process: (Ignore connection portion)
Now we know how to transfer files, but how do we enter the OBEX mode? A mobile phone company makes their own decision on how to enter the OBEX mode.
Siemens
First you must be able to send an AT command. Then you send "AT^SQWE=0", waiting for a response, and then "AT^SQWE=3", and wait for the response. Then you will be in the OBEX mode.
Tip: I can also see a serial status from GIPSY to OBEX in the phone's factory mode on Siemens M55.
In order to quit the OBEX mode, please send "+++" and wait for more than a second.
Motorola C650
You must be able to send an AT command. Then send "AT+MODE=22", and you are in the OBEX mode.
To leave OBEX mode, you should close your port and re-open, and then everything will be OK.
Sony Ericssion T618/K508
You must be able to send an AT command. Then send "AT*EOBEX", and you will be in OBEX mode.
My Dreamworld.Protocol.OBEXClient.Command
class provides basic operations of OBEX, such as connecting, disconnecting, folder-listing, and file transferring. Your work is to implement EnterOBEX()
and ExitOBEX()
functions. For more details and as an example, please see my Siemens CX6C project.
As I mentioned above, the FBUS protocol has no detailed documents on the Internet. I know of an open-source project called Gnokii which has done some work on this protocol, but it is still not detailed enough. What to do next? I can only monitor the file transfer process other software, analyse it, and then implement it.
To enter the Nokia FBUS protocol, you must first set your baudrate to 115200, and set DTR=off and RTS=off.
FBUS calls every data segment as a Frame. Here is the Frame format for FBUS version 2 (From the Gnokii document):
[FrameID, DestDev, SrcDev, MsgType, 0x00, FrameLength,
{block}, FrameToGo, SeqNo, PaddingByte?, ChkSum1, ChkSum2]
Name |
Description |
FrameID |
0x1c: IR/FBUS 0x1e: Serial/FBUS |
DestDev , SrcDev |
0x00: Mobile Phone 0x0c, 0x10: TE (PC) |
MsgType |
See Gnokii for details |
FrameLength |
length of [block] + 2 |
FrameToGo |
0x0n means there are n-1 frames to go after this frame. |
SeqNo |
[0xXY] X=4: first block X=0: continuing block Y: sequence number |
PaddingByte |
0x00 if FrameLength would be an odd number, anyway it doesn't exist |
ChkSum1 |
XOR on Frame's odd numbers |
ChkSum2 |
XOR on Frame's even numbers |
Let's first look at two FBUS segments from a mobile to a PC:
Request from PC
You will notice that before sending the first Frame, plenty of 0x55s are sent. These 0x55s are known as a Sync Signal. Why send 0x55s instead of other hex values? You know that the binary for 0x55 is 1010101, and when on the serial line, it will be 01010101. These "0x55"s will be linked together as repeating "01"s, and when the phone receive enough "01"s to ensure that the line is OK, the phone will switch to the FBUS mode.
Let's look at:
Frame 1
This is a request Frame which requests for the phone version info:
Frame 2
This is an acknowledgement frame. Every frame TE send will return an acknowledgement frame with MsgID
=0x7F. Its format is:
{FrameID, DestDev, SrcDev, 0x7F, 0x00, 0x02,
ID_Command, ID_SeqNo, ChkSum1, ChkSum2}
ID_Command
: The commandID
that you are acknowledging.
ID_SeqNo
: The sequence number that you are acknowledging.
In our example, the ID_Command
is 0xD1 which is the ID in our request 0xD1.
The ID_SeqNo
is a number that equals to (SeqNo AND 0x0F
). Here, (0x40 AND 0x0F) = 0x00.
Frame 3
This is the version info we get from the phone. Note here that the sequence is 0x44. This means the sequence number is 4 right now. Every time you send a new frame, the sequence number should be (seq+1) MOD 8
. So the sequence number of Frame 5 should be 5.
Frame 4
Acknowledgement frame to the last frame. You must return an acknowledgement to the last frame as soon as you receive and check the frame. Normally, you must respond, approximately, within 300ms. If not, the phone will retry thrice to send the same frame. If no acknowledgement frame is received by the phone, the phone will disconnect the link.
I think it's hard to give a full example to show this, but I'll show how to do it. Please look at my draft code for an example.
- Step 1: Switch to FBUS mode. As you know, send '0x55' several times.
- Step 2: Send, what I call, initialization frames to the phone. See my
Sub Prepare()
for details.
- Step 3: Send the full file name including the path on the phone and prepare to send the data. See
privateSendFile()
.
- Step 4: Send the data. See
privateSendFile()
.
- Step 5: Send the complete message.
My code is a draft code, so it will be hard to read, and it will have bugs because I have no more detailed documents about FBUS. I learned these steps by monitoring other software. If you like, you can try and monitor the MobTime Cell Phone manager.
Some of the AT commands are listed below:
AT command |
Description |
AT+FSCD="<DIR>" |
Change to <DIR> |
AT+FSDI="<DIR>" |
Directory information |
AT+FSDL="<DIR>" |
Directory list |
AT+FSFW=-1, "<FILENAME>", 0, "", <LEN>, <CRC> |
Send a file. |
AT+FSFE=0, "<FILENAME>" |
Delete a file. |
Let's see an example:
Request
Change the directory to "/å?¾ç?". Don't care the folder name here.
If your phone is English, then it will be /Picture
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D ".
Answer
Folder Successfully changed.
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D 0D 0A 4F 4B 0D 0A "...OK..
Request
Repeat. I don't know why.
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D ".
Answer
Repeat. I don't know why.
41 54 2B 46 53 43 44 3D 22 2F E5 9B BE E7 89 87 AT+FSCD="/å?¾ç??
22 0D 0D 0A 4F 4B 0D 0A "...OK..
Request
Write a file. 18752 is the length.
880445898 is unsigned CRC32 code for the file.
41 54 2B 46 53 46 57 3D 2D 31 2C 20 22 E6 B5 8B AT+FSFW=-1, "æµ?
E8 AF 95 2E 6A 70 67 22 2C 20 30 2C 20 22 22 2C è¯.jpg", 0, "",
31 38 37 35 32 2C 38 38 30 34 34 35 38 39 38 0D 18752,880445898.
Answer
OK. You can continue. "##>" indicates continue your transfer.
41 54 2B 46 53 46 57 3D 2D 31 2C 20 22 E6 B5 8B AT+FSFW=-1, "æµ?
E8 AF 95 2E 6A 70 67 22 2C 20 30 2C 20 22 22 2C è¯.jpg", 0, "",
31 38 37 35 32 2C 38 38 30 34 34 35 38 39 38 0D 18752,880445898.
23 23 3E 0D 0A ##>..
Request
Send data. Maximum data length is 512 bytes.
FF D8 FF E0 00 10 4A 46 49 46 00 01 02 00 00 01 ÿØÿà..JFIF......
......
<Total 512 bytes data here>
Answer
Please continue.
0D 0A 23 23 3E 0D 0A ..##>..
Request
...
<Continue data segment>
Answer
...
Request
Send last segment of data. Phone will calculate
total data you send. When phone received
18752 bytes, it will return OK
91 56 53 E9 BF 5B 55 68 AF 8E 35 66 87 06 3D 35 VSé¿[Uh¯?5f.=5
<.......>
E3 C6 63 31 E3 C6 63 31 E3 C6 63 31 E3 C7 FF D9 ãÆc1ãÆc1ãÆc1ãÇÿÙ
Answer
Phone has received all your data.
0D 0A 4F 4B 0D 0A ..OK..
That's all the process is, easy and human-readable. Try to program it!
Now it's time to rest or have a coffee. I think file transferring should not be as mysterious as you think.
The OBEX protocol is widely used and very powerful, but not as tiny as FBUS. FBUS is hard to use, and lacks detailed documents. Otherwise, Samsung's AT command is very clear to use.
It will be a long way to make a really stable file transferring tool; I'm learning, and so are you. Let's share our failures and successes. Contact me if you have problems reading my article.