SRI International Computer Science Laboratory


Connecting your Linux Laptop (Particularly Your Asus Eee) to Your Cellphone via Bluetooth

John Rushby


Note: the original material here is rather old (I wrote it in 2003), though its basic principles remain correct and I still receive occasional thankyou emails from people who found it useful.

However, when I referred to it myself in early 2008 to get bluetooth working with my Asus Eee, I found I had to deal with quite a few additional difficulties. So I've added a new section on those.


Version from 2003

The following worked for me. I distilled it from various Bluetooth howtos, plus quite a lot of experimentation. My thanks to the original howto authors, and to the developers of all this fine software, and my apologies for not acknowledging them by name.

I have a Belkin Bluetooth USB adapter (model F8T003 Ver 2) I bought for about $40 in Frys. My laptop is a Toshiba Libretto L5 runing RedHat 7.3 with the 2.4.18 kernel. My cellphone is an Ericsson R520m tri-band GSM.

Kernel Stuff

The recommended Bluetooth protocol stack for Linux is Bluez. It's built in to recent kernels, but I am running a version of the 2.4.18 kernel that has been patched to suit the peculiarities of my laptop so I preferred to start from there. This requires you do not enable Bluetooth in the kernel as that installs some inferior package that gets in the way.

Instead, download the Bluez kernel version 2.3 tar file into a subdirectory of the kernel source tree and compile that as a module. Then you need to download and compile various Bluez library and utility packages. The tarballs I used were

Next, you need to create the /dev/rfcommX devices, and the file to do this is missing from these tar files. The recipe to do it is
  #!/bin/sh -f
  mknod /dev/vhci c 10 250
  chmod 664 /dev/vhci

  C=0;
  while [ $C -lt 256 ]; do
  if [ ! -c /dev/rfcomm$C ]; then
  mknod -m 666 /dev/rfcomm$C c 216 $C
  fi
  C=`expr $C + 1`
  done
Then you need to customize the file /etc/bluetooth/hcid.conf. Here's what I use.
  #
  # HCI daemon configuration file.
  #
  # $Id: hcid.conf,v 1.3 2002/07/18 18:12:46 maxk Exp $
  #

  # HCId options
  options {
	  # Automatically initialize new devices
	  autoinit yes;

	  # Security Manager mode
	  #   none - Security manager disabled
	  #   auto - Use local PIN for incoming connections
	  #   user - Always ask user for a PIN
	  #
	  security auto;

	  # Pairing mode
	  #   none  - Pairing disabled
	  #   multi - Allow pairing with already paired devices
	  #   once  - Pair once and deny successive attempts
	  pairing multi;

	  # PIN helper
  #       pin_helper /bin/bluepin;
	  pin_helper /etc/bluetooth/givepin;
  }

  # Default settings for HCI devices
  device {
	  # Local device name
	  #   %d - device id
	  #   %h - host name
	  name "BlueZ (%d)";

	  # Local device class
	  class 0x100;

	  # Default packet type
	  pkt_type DH1,DM1,HV1;

	  # Inquiry and Page scan
	  iscan enable; pscan enable;

	  # Default link mode
	  #   none   - no specific policy 
	  #   accept - always accept incoming connections
	  #   master - become master on incoming connections,
	  #            deny role switch on outgoing connections
	  #
	  lm master;
	  #
	  # lm accept,master;

	  # Default link policy
	  #   none    - no specific policy
	  #   rswitch - allow role switch
	  #   hold    - allow hold mode
	  #   sniff   - allow sniff mode
	  #   park    - allow park mode
	  #
	  #lp hold,sniff;
	  #
	  lp hold,sniff,park;

	  # Authentication and Encryption
	  auth enable;
	  #encrypt enable;
  }

The file /etc/bluetooth/givepin contains the pin that will be used to authenticate the pairing between the laptop and the phone. It should contain something like
  #!/bin/sh
  echo "PIN:123456"
With that in place, you can plug the Bluetooth device into a USB port and do
  /etc/init.d/bluetooth start
Then
  hciconfig -a 
should reveal the device (use hciconfig hci0 up if necessary) and produce something like this.
  hci0: Type: USB 
        BD Address: 00:0A:3B:50:94:75 ACL MTU: 192:8  SCO MTU: 64:8
        UP RUNNING PSCAN ISCAN AUTH 
        RX bytes:400 acl:0 sco:0 events:20 errors:0
        TX bytes:570 acl:0 sco:0 commands:19 errors:0
        Features: 0xff 0xff 0x0b 0x00
        Packet type: DM1 DH1 HV1 
        Link policy: HOLD SNIFF PARK 
        Link mode: MASTER 
        Name: 'BlueZ (0)'
        Class: 0x000100
        Service Classes: Unspecified
        Device Class: Computer, Uncategorized
        HCI Ver: 1.1 (0x1) HCI Rev: 0x20d LMP Ver: 1.1 (0x1) LMP Subver: 0x20d
        Manufacturer: Cambridge Silicon Radio (10)

If the last few lines are missing, or you get an error message, then try

  hciconfig hci0 down
  hciconfig hci0 up
  hciconfig -a
Don't proceed until you get the full response--it won't work.

Binding and Pairing

Next, you need to get the laptop to find the phone. Turn on the phone and do whatever is necessary in its menus to turn on Bluetooth and make it "discoverable". Then do
  hcitool scan
You should get
  Scanning ...
        00:80:35:2A:BA:DB       R520m
where R520m is the name of the phone (which you can change by tinkering in the phone's menus) and the other stuff is its Bluetooth address (and, no, that's not the real address of my phone). You can check that you are communicating with the phone by doing
  l2ping 00:80:35:2A:BA:DB
Next, do the following (I think the phone must still be in discoverable mode for this to work)
  sdptool browse
This will produce something like
  Inquiring ...
  Browsing 00:80:35:2A:BA:DB ...
  Service Name: Dial-up Networking
  Service RecHandle: 0x10000
  Service Class ID List:
    "Dialup Networking" (0x1103)
    "Generic Networking" (0x1201)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 1
  Profile Descriptor List:
    "Dialup Networking" (0x1103)
      Version: 0x0100

  Service Name: Fax
  Service RecHandle: 0x10001
  Service Class ID List:
    "Fax" (0x1111)
    "Generic Telephony" (0x1204)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 2
  Profile Descriptor List:
    "Fax" (0x1111)
      Version: 0x0100

  Service Name: Voice gateway
  Service RecHandle: 0x10002
  Service Class ID List:
    "Headset Audio Gateway" (0x1112)
    "Generic Audio" (0x1203)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 3
  Profile Descriptor List:
    "Headset" (0x1108)
      Version: 0x0100

  Service Name: Serial Port 1
  Service RecHandle: 0x10003
  Service Class ID List:
    "Serial Port" (0x1101)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 4

  Service Name: Serial Port 2
  Service RecHandle: 0x10004
  Service Class ID List:
    "Serial Port" (0x1101)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 5

  Service Name: OBEX Object Push
  Service RecHandle: 0x10005
  Service Class ID List:
    "OBEX Object Push" (0x1105)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 10
    "OBEX" (0x0008)
  Profile Descriptor List:
    "OBEX Object Push" (0x1105)
      Version: 0x0100

  Service Name: IrMC Synchronization
  Service RecHandle: 0x10006
  Service Class ID List:
    "IrMCSync" (0x1104)
  Protocol Descriptor List:
    "L2CAP" (0x0100)
    "RFCOMM" (0x0003)
      Channel: 11
    "OBEX" (0x0008)
  Profile Descriptor List:
    "IrMCSync" (0x1104)
      Version: 0x0100
What you are looking for is the channel associated with "Dialup Networking" (DUN); here, it's 1. Now you can do
  rfcomm bind 0 00:80:35:2A:BA:DB 1
where the first digit is the rfcomm device number, the second is the bluetooth address of the phone, and the third is its DUN channel. This connects /dev/rfcomm0 to your phone.

At some point, you'll need to establish "pairing" between your computer and the phone. You can try to provoke the phone into initiating pairing by digging around in its menus (it should detect a device called Bluez (0) ) but I've not found this to work because the laptop isn't in a mode to confirm the pin. So just proceed, but keep an eye on the phone in case it pops up with a question about pairing and requests a pin, in which case you'll need to type in the one from your /etc/bluetooth/givepin. Once they've paired successfully the devices seem to remember each other and don't need to do it again.

Connecting

Finally, you can initiate a ppp connection over the phone. If you want to use kppp to manage the connection, you'll need to create a symlink to /dev/modem because kppp doesn't offer /dev/rfcomm0 as an option
  rm -rf /dev/modem
  ln -s /dev/rfcomm0 /dev/modem
For CSD (i.e., using the phone as an ordinary modem), you now just use kppp or whatever to dial your ISP as usual; for GPRS, first make sure you have a single data account in the phone that is pointing to the correct APN (you get this from your cellphone service provider and should make sure that it's working using the WAP browser built into the phone), then have kppp dial the number *99#. Depending on your service provider, you may need to set a user name and password for pap authentication. For GPRS on T-Mobile, a space as username and password seems to work.

The ppp capabilities in the phone are quite limited, so you may have to turn off several options in kppp; see the pppd command line below for an example. Also, it seems important to have the following in your /etc/modules.conf.

  options ppp_async flag_time=0
Other useful ppp entries to have in this file may be the following
  ### automate ppp modules loading ###
  alias /dev/ppp          ppp_generic
  alias char-major-108    ppp_generic
  alias tty-ldisc-3       ppp_async  
  alias tty-ldisc-14      ppp_synctty
  alias ppp-compress-21   bsd_comp   
  alias ppp-compress-24   ppp_deflate
  alias ppp-compress-26   ppp_deflate
If you don't use kppp, the following command invokes ppp directly (it needs to be all on one line)
pppd /dev/rfcomm0 debug nocrtscts noipdefault novj novjccomp defaultroute
  connect 'chat -v -f /etc/ppp/r520m' &
where, for GPRS, /etc/ppp/r520m contains the following chat script.
  "" "ath"
  OK "atdt*99#"
  CONNECT
If you are using a CSD connection, then your chat script will need to contain the appropriate dialog for calling and logging in to your ISP.

Once you've got things to work by hand, you can create a shell script to automate it. I use the following (the pppd command needs to all be on one line).

  #!/bin/sh -f
  ifconfig eth0 down
  killall pppd
  /etc/init.d/bluetooth restart
  echo Please insert Bluetooth device and hit enter when ready
  read
  hciconfig hci0 down
  hciconfig hci0 up
  hciconfig -a
  echo If you did not see about 15 lines ending in Manufacturer, hit ctrl-c and try again
  echo Otherwise, please make phone discoverable and hit enter when ready
  read
  echo Please hit ctrl-c when ping echoes start
  l2ping 00:80:35:2A:BA:DB
  rfcomm release 0
  rfcomm bind 0 00:80:35:2A:BA:DB 1
  pppd /dev/rfcomm0 debug nocrtscts noipdefault novj novjccomp
     defaultroute connect 'chat -v -f /etc/ppp/r520m' &
  echo Bluetooth link will be running in a few seconds time
  echo Please check the phone for pin requests or connecting messages
That's it. I hope it helps.

Updates from 2008 for the Asus Eee

The Asus Eee is a dream come true: a tiny laptop that comes with Linux already installed! Furthermore it's cheap: the model I have, which is called the 4G Surf, costs just $350. It has no hard disk; instead it uses a 4GB flash drive. It uses a version of the Xandros Linux distribution and comes with Firefox, Thunderbird, Open Office, Acroread, Skype, and several other essential applications (e.g., music, picture, and video players) already installed, and still has more than half the "disk" free. You'll need to install Emacs, LaTeX, the basic build utilities (gcc etc.), plus whatever specialized applications you use. I have PVS, SAL, Yices, and lots of other stuff and still have plenty of space left.

The Eee also has a slot for an external SD flash card: I have a 4GB Class 6 card in there; note that it must be a really fast card and Class 6 seems to be about the minimum that works (it's write speed that matters). Every paper I've ever written, every talk I've given (at least, since I stopped using handwritten foils), and loads of other work-related stuff occupies less than 1GB, leaving plenty of space for music and photos and whatever.

Flash memory has a limited number of write cycles (100,000 or so), so I think it's best to keep applications on the internal drive (which is soldered in place), and data on the external drive (which you can replace when it wears out).

There's a very useful set of resources for the Eee at http://www.eeeuser.com/ including forums and a wiki, and that's where I learned much of what's reported here.

The Eee has excellent built-in WiFi, an Ethernet port, and 3 USB ports. It's reported that USB 3G modems such as the Huawei E220 work right out the box. However, it does not have built-in networking via Bluetooth-to-phone, so getting that working is the subject of this section.

Things That Are Pretty Much The Same

The basic principles remain the same as in the 2003 description given above. However, much of the software is already installed in the Eee's Linux, so you basically just need to tweak some configuration files. You have to be root or precede everything with sudo to edit these files or to give most of the commands.

Most importantly, the Bluez protocol stack is already there, and it starts automatically. In the interests of a fast boot (it starts from cold in about 30 seconds) the Eee bypasses the usual Linux boot process and it also uses a lightweight window manager called IceWM. (It comes with instructions for enabling the KDE desktop, and many people have installed other window managers and even other Linux distributions; I don't see the point of this--I'm indifferent to the window manager and desktop that's used, as long as I can get to Emacs and a shell prompt--and I prefer the fast boot and out-the-box hardware compatibility of the default system to the claimed benefits of other distributions. The Eee also comes with the drivers and instructions for installing something called Windows XP--I don't suppose that will ever catch on).

Anyway, the Eee boot is controlled by the file /usr/sbin/services.sh, and down at the bottom of that file we find

/etc/init.d/dbus start
/etc/init.d/bluetooth start

Examination of the /etc/init.d/bluetooth script reveals that it starts hci. So we should be able to simply stick a Bluetooth dongle into one of the USB ports and have things work right away. But first we should check that the config file /etc/bluetooth/hcid.conf looks similar to the one below (which is what I use).

#
# HCI daemon configuration file.
#

# HCId options
options {
	# Automatically initialize new devices
	autoinit yes;

	# Security Manager mode
	#   none - Security manager disabled
	#   auto - Use local PIN for incoming connections
	#   user - Always ask user for a PIN
	#
	security auto;

	# Pairing mode
	#   none  - Pairing disabled
	#   multi - Allow pairing with already paired devices
	#   once  - Pair once and deny successive attempts
	pairing multi;

	# Default PIN code for incoming connections
	pin_helper /etc/bluetooth/givepin;
}

# Default settings for HCI devices
device {
	# Local device name
	#   %d - device id
	#   %h - host name
	name "Cirago";

	# Local device class
	class 0x3e0100;

	# Default packet type
	#pkt_type DH1,DM1,HV1;

	# Inquiry and Page scan
	iscan enable; pscan enable;

	# Default link mode
	#   none   - no specific policy 
	#   accept - always accept incoming connections
	#   master - become master on incoming connections,
	#            deny role switch on outgoing connections
	lm accept;

	# Default link policy
	#   none    - no specific policy
	#   rswitch - allow role switch
	#   hold    - allow hold mode
	#   sniff   - allow sniff mode
	#   park    - allow park mode
	lp rswitch,hold,sniff,park;

        discovto 0;

}
Differences from the hcid.conf file shown earlier are that the local device class field was previously 0x100 and here it's 0x3e0100. According to the hciconfig man page, the class is "a 24-bit hex number describing the class of device, as specified in section 1.2 of the Bluetooth Assigned Numers document". The 100 at the end says this is a computer and the 3e at the front indicates some of the services it can perform, so I guess this form is to be preferred to the simpler one I used in 2003. The other difference is the addition of the discovto 0 field. This says the computer should become discoverable and stay that way. This is reported to help in the pairing process (see later).

I use a tiny Bluetooth dongle (the name says "Cirago") that sticks out less than half an inch from the USB port. As soon as I insert it, the Eee recognizes it and hciconfig -a reports its properties.

Next, we can turn on the phone and do hcitool scan, l2ping, and sdptool browse as before. Assuming those all work as expected, we can move on to the new stuff.

Things That Are Different

The Eee already has the rfcomm devices, so we don't need to create them like we did in 2003 and we don't manipulate them explicitly. Instead, we set them up in the config file /etc/bluetooth/rfcomm.conf.

I have two phones, so I connect one to rfcomm0 and the other to rfcomm1. In each case, the device field specifies the Bluetooth address of the phone concerned (as revealed by hcitool scan) and the channel gives its DUN (Dial Up Networking) channel (as revealed by sdptool browse). Actually, I have a third phone--it's a 3G Nokia 6650 I use in Japan and that also works in Europe; next time I'm in a country where it works (it won't even start in the USA), I'll add a section to connect that to rfcomm2.

#
# RFCOMM configuration file.  
#

rfcomm0 {
	bind yes;
	device 00:17:7D:99:A3:31;
	channel 3;
	comment "SGH T-439 phone";
}

rfcomm1 {
	bind yes;
	device 00:80:35:2A:BA:DB;
	channel 1;
	comment "R520m phone";
}
Unlike 2003, we don't supply the parameters to pppd explicitly, either, but instead do it through the "peers" mechanism.

For my Samsung SGH T439 phone (this is a GSM quad-band flip phone that is given away free with most T-Mobile USA plans), I created the file /etc/ppp/peers/t439 with the following contents.

/dev/rfcomm0 115200
connect 'chat -v -f /etc/ppp/chat-t439'
-detach
noauth
defaultroute replacedefaultroute usepeerdns noipdefault
local
default-asyncmap
novj novjccomp nopcomp noaccomp noccp nobsdcomp nodeflate 
lock
I've not experimented to see exactly which options are necessary and which not. It is important to say nothing about lcp-echo-interval and similar: these are intended to keep the connection alive but instead they kill it.

Next, create the file /etc/ppp/chat-t439 with the contents

"" "ATH"
OK "ATDT*99#"
CONNECT
I've not found it necessary to use the CDGCONT constructions you sometimes read about to set the APN. A locked phone like the T439 comes with the APN wired in, and for other phones it's best to set it in the phone's own menus, as then you can use the Wap browser and other Internet capabilities in the phone itself. If you cannot figure out how to set the APN etc., see if your cellphone service provider has a configurator that will download the correct settings. T-Mobile USA has such a service: I was in Europe and couldn't figure out how to set up my Nokia 6650 so I used their config web page (I had to tell it I had a 6651 as the 6650 isn't sold in the USA) and it downloaded the settings just fine, and for free.

For the my Ericsson R520m phone, I have a file /etc/ppp/peers/r520m that is just like t439, except the first two lines are

/dev/rfcomm1 115200
connect 'chat -v -f /etc/ppp/chat-r520m'
That is, it uses rfcomm1 instead of rfcomm0 and has its own chat script /etc/ppp/chat-r520m with the following contents.
"" "ATH"
OK "AT&FE0S0=0;+cbst=80,0,1;+chsn=4,2,0,12"
OK "ATDT*99#"
CONNECT
I learned the initialization string in the second line above by decoding the R520m script that came with my Macbook; I'm pretty sure it can be deleted--I started using it while I was trying to debug a problem whose true resolution is described later.

Now, we can do

pppd call t439
and the Eee should connect to the Internet via the T439; when you are done, do killall -9 pppd. That is, it should connect if it's already paired with the Bluetooth dongle--see the next section.

If you want to leave the Bluetooth dongle in the USB port when you are done (a good idea, as it's easy to lose if you take it out), then

sudo hciconfig hci0 down
will stop the blue light flashing. Remember to turn it back on before you attempt another connection.

Pairing

Recent Linuxes use a "dbus" protocol to communicate among components and for Bluetooth pairing we need a pin agent that knows about this. The old givepin and discovto 0 method for supplying a pairing pin doesn't know about dbus and works (if at all) only when the phone is able to initiate the pairing. The R520m can do this, but the T439 cannot. Instead, the pppd invocation above initiates pairing from the computer and the phone asks you to enter the pin--and nothing you enter will work.

The Bluez pin agent for dbus is called passkey-agent but, unfortunately, it is not included with the Eee (nor most other distributions)--the source is there, but not a compiled binary. To compile it yourself, you need the dbus development libraries. I got a suitable binary from somewhere and I've put a copy here. Download that file and put it in a directory like /usr/sbin and make it executable and do a rehash. Then, before you call pppd do

passkey-agent --default 1234 &
When the phone asks you for the pin, type in 1234 and you should be in business. Kill passkey-agent afterward. You only need to do this once to set up pairing. If you are having trouble, try deleting the subdirectories of /var/lib/bluetooth as a lot of stuff is cached there and you may be fighting data from previous attempts.

Module Options

The T439 (and, I suspect, any modern phone) works well with the recipe above. My R520m did not, however. The symptoms were that it would connect 1 time in 20, and the other 19 times tcpdump -ni ppp0 revealed that it spent all its time querying the name servers: it was obviously unable to actually communicate. In 2003, I mentioned that for this phone, the module option
  options ppp_async flag_time=0
had to go in the /etc/modules.conf file. It turns out that on the Eee it has to go in the file /etc/modprobe.d/bluez. Once I did that the R520m worked fine (though the T439 goes twice as fast--that's presumably because it can do EDGE).

File Transfer

A modern phone like the T439 can record photos and movies, and play music, so it might be useful to be able to move files back and forth between the phone and the Eee. The Linux software that does this is obexftp. I installed it with
sudo apt-get install obexftp
and followed the instructions in this howto and it worked fine. Note that you don't need to specify the OBEX file transfer channel explicitly--it finds it out for itself--but you do need to learn (by experimenting) the correct directories on the phone to put and get files of various types.

Go my "email on the road" page

Return to my home page