Exchange data freely between your Bluetooth device and your Linux box.
Getting on the Net [Hack #17] from anywhere your cell phone works is pretty darn cool, but your phone probably has other features. Maybe someone messaged you a photo from their family barbecue that you want to copy over to your laptop. Or maybe you just want to install some applications on your shiny new phone.
The heart of file transfer over Bluetooth
is called the Object
Exchange
, or OBEX, protocol, a binary file
transfer protocol run over not merely Bluetooth, but also Infrared
and even generic TCP/IP. The
OpenOBEX project at
http://openobex.sf.net/ offers
the most ubiquitous open source implementation of the protocol. You
can get packages for libopenobex
and
openobex-apps
from the sid
distribution, and Red Hat packages for openobex
can be had from the
SourceForge site
or on rpmfind.net. Bluetooth actually supports
two different OBEX profiles for transferring files:
OBEX Push, which is primarily used
for dumping individual files to a Bluetooth device, and OBEX File
Transfer, which supports a richer set of file exchange operations.
Unfortunately,
the present state of the art in Bluetooth file transfer using Linux
is still in considerable flux. The
openobex-apps
package contains an
obex_test
application, which offers one
very rudimentary way of sending files to your Bluetooth devices.
First, you need to figure out which Bluetooth channel your phone or
other device uses for OBEX File Transfer; to do this, type:
# sdptool search FTRN
Inquiring ...
Searching for FTRN on 00:11:22:33:44:55 ...
Service Name: OBEX File Transfer
Service RecHandle: 0x10003
Service Class ID List:
"OBEX File Transfer" (0x1106)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 10
"OBEX" (0x0008)
Now you can try connecting to the device with
obex_test, using the -b
option (for Bluetooth), the BD address of the device, and the FTRN
channel number:
$obex_test -b 00:11:22:33:44:55 10
Using Bluetooth RFCOMM transport OBEX Interactive test client/server. >c
Connect OK! Version: 0x10. Flags: 0x00 >x
PUSH filename>/home/sderle/images/image.jpg
name=/home/sderle/images/image.gif, size=7294 Going to send /home/sderle/images/image.gif(opt21.gif), 7294 bytes Filling stream!
obex_test proceeds to display some progress messages, followed by a confirmation:
Made some progress... Made some progress... Made some progress... Filling stream! PUT successful!
The file should appear on your device. Similarly, obex_test can receive files sent from your device, if you configure your computer’s Bluetooth interface to answer to OBEX Push requests, again using sdptool with the same channel your device uses for OBEX Push:
$sdptool add --channel=10 OPUSH
$obex_test -b 00:11:22:33:44:55 10
Using Bluetooth RFCOMM transport OBEX Interactive test client/server. >s
obex_test should print a blank line and then
pause. Now send a file from your phone via Bluetooth.
You’ll see a ton of status messages, and then
obex_test will report that it’s
finished. You should be able to find your file in
/tmp
.
The problem with obex_test, other than a total lack of documentation, is that it’s entirely driven by terminal-based user interaction. What if we want to script file transfers or be able to receive files automatically? Another, probably easier way of getting files from your computer to your phone involves a little app called ussp-push , which you can get from http://www.unrooted.net/hacking/ussp-push.tgz. ussp-push is based on some code from the Affix stack, but actually relies on OpenOBEX. Also, it doesn’t compile at present right out of the box, so we’ll use Perl to tweak it so that it compiles properly with modern versions of OpenOBEX:
#tar xfz ussp-push.tgz
#cd ussp-push
#perl -pi -e 's/custfunc.userdata/custfunc.customdata/g' obex_main.c
#make
... #cp ussp-push /usr/local/bin
ussp-push relies on having an RFCOMM serial device bound to the Bluetooth channel your device uses for OBEX Push, so we’ll first need to fire up sdptool again, and then use rfcomm to bind the device to the listed channel:
#sdptool search OPUSH
Inquiring ... Searching for OPUSH on 00:11:22:33:44:55 ... Service Name: OBEX Object Push Service RecHandle: 0x10004 Service Class ID List: "OBEX Object Push" (0x1105) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 9 "OBEX" (0x0008) #rfcomm bind /dev/rfcomm1 00:11:22:33:44:55 9
Now you can use ussp-push to send files to your device.
$ ussp-push /dev/rfcomm1 /home/sderle/images/image.jpg image.jpg
ussp-push takes three arguments: an RFCOMM
device, a local file to push, and the name of the file to save it as
on the remote side. When you run ussp-push,
you’ll see an avalanche of progress info, hopefully
concluding with the file appearing on your phone. If you create an
entry for the new RFCOMM device in
/etc/bluetooth/rfcomm.conf
, you can have the device bound on boot.
Save the following wrapper script as
btpush
,
and save it somewhere handy (such as your ~/bin
directory). You can then use it to trivially send files directly to
your phone:
#!/bin/bash # btpush - send files to a Bluetooth device using ussp-push # just run it as: btpush <file> ussp-push /dev/rfcomm1 $1 `basename $1`
If you get permissions issues when running
ussp-push, make sure your
/dev/rfcomm*
devices are group-writeable, and
are owned by a group that you’re a member of.
Similarly, you can receive files using another small app called
obexserver
, which you
can fetch from http://www.frasunek.com/sources/unix/obexserver.c.
obexserver needs to be built together with
openobex-apps. Once you’ve
built openobex-apps, do the following from
within the top-level source directory:
#cd src
#wget http://www.frasunek.com/sources/unix/obexserver.c
#gcc -o obexserver obexserver.c libmisc.a -lopenobex
#cp obexserver /usr/local/bin
To receive files, first set up OBEX Push service on your computer by
running sdptool add --channel=10 OPUSH
, changing
the channel as necessary to match the one your device uses for OBEX
Push. Now you can just run obexserver without
arguments, and send a file from your phone.
obexserver will receive the file, store it in
/tmp
, and exit.
Being able send files from phone to computer and back is nice, but
having to send and receive files individually
doesn’t present the absolutely most convenient
interface. Fortunately, if your Bluetooth device is running the
SymbianOS or EPOC
operating system—this includes Series 60
phones and the
Ericsson P800—you can actually mount your
device’s filesystem on your computer via
NFS. The package
that performs this minor miracle is called p3nfs, and it’s available
at http://www.koeniglich.de/p3nfs.html. The
source distribution comes with binaries to run on your phone, in case
you don’t have a cross-compiler (which is likely).
The phone application is called
nfsapp
, and you can find the appropriate
binary version for your phone in the bin/
subdirectory, with a .sis
extension. Use one of
the methods just described to send the appropriate SIS file to your
phone and install it there. Next, build and install p3nfsd in the
usual way. If you installed the RPM provided by
koeniglich.de
, you can find the SIS files in
/usr/share/doc/p3nfs-[version]
.
You’ll want to create a mount point in your
filesystem for the NFS share; p3nfs uses
/mnt/psion
by default. Also, p3nfs needs its own
RFCOMM device, so you’ll need set one up. If
you’re running a Nokia phone,
you’ll probably want to bind to channel 4;
otherwise, you may be using channel 3.
#mkdir /mnt/phone
#rfcomm bind /dev/rfcomm2 00:11:22:33:44:55 4
Now, start nfsapp on your phone.
Don’t worry if you pick the wrong channel at
first—when you run nfsapp on your phone,
it will tell you which channel it’s listening to. If
you told rfcomm to bind to the wrong one, just
run rfcomm unbind /dev/rfcomm2
and try the right
channel. At first, nfsapp defaults to listening
to the infrared port—click the joystick or press the
p
key to cycle between IR, Bluetooth, and TCP
transport. Once you select Bluetooth, nfsapp
gives you 30 seconds to start p3nfs on your computer. Assuming
everything else is configured correctly, you should be able to start
p3nfsd as follows:
# p3nfsd -series60 -tty /dev/rfcomm2 -dir /mnt/phone -user sderle
p3nfsd: version 5.13a, using /dev/rfcomm2 (115200), mounting on /mnt/phone
p3nfsd: to stop the server do "ls /mnt/phone/exit". (pid 3274)
p3nfsd will probably take a few seconds to finish mounting. A quick
look at lsmod
will verify that, in fact,
it’s using your kernel’s NFS
support. You’ll want to replace
-series60
with -UIQ
or another
option if you’re not running a Series 60
phone—run p3nfsd without any options for a list.
You’ll want to alter the -tty
,
-dir
, and -user
options as
appropriate. The -user
option
isn’t strictly necessary, but p3nfsd mounts the
share with user-only read and execute permissions, so if you
don’t use it, you’ll need to be
root to browse the share. Now you should be able to
cd
into /mnt/phone
, and do
all the things you’re accustomed to doing in a
Unix-like NFS mount. You’ll need to ls /mnt/phone/exit
to unmount the share, which is a little
weird. Otherwise, p3nfsd unmounts after a few minutes of
inactivity—you can control the timeout using the
-timeout
option.
By this point, you’ve got several options for
exchanging data between Bluetooth devices. Obviously, you can easily
reuse these techniques to exchange files between two
Bluetooth-equipped Linux machines as well, and, in fact, these same
methods work pretty well for infrared file transfers, with a little
tweaking, but that’s beyond the scope of this hack.
One last thing: if you want your new RFCOMM devices to be there the
next time you boot, don’t forget to add entries for
them to /etc/bluetooth/rfcomm.conf
. Now start
installing those applications!
—Schuyler Erle
3.144.104.29