Saturday, February 23, 2008

Bash Scripting: A new beginning

Recently, I found that due to excessive amount of work, I have to automate tasks as much as possible. So, here I am learning to script as much as possible in my linux box. I've just started to script in Bash and here's the first working script.

#!/bin/bash
#
# This script suppose to setup the machine to connect to Jalawave
# using rfcomm0 interface and reports any error it encounters.
# The following is the logic.
# 1. Check whether the prerequisite is met. Abort if not.
# 2. Check whether rfcomm0 exists. If it isn't, then bind it
# using rfcomm.
# 3. Check whether interface ppp0 exists. If it doesn't exist,
# execute "wvdial bluetooth" in the background and wait
# until ppp0 interface created.
# 4. Check whether the default gateway to Jalawave has been
# created by the route program. Create one if it's not
# been created yet.
# 5. Update the nameserver configuration to the right value
#

# Error codes
E_NOT_ROOT=66 # Todo: you have to fix the error code
E_WVDIAL_STOP=67

COM_DEVICE=rfcomm0
PPP_INTERFACE=ppp0
JALA_GW=10.6.6.6

#
# 1. Check whether the prerequisite is met. Abort if it isn't.
#

#
# Check whether we are superuser
#
if [ "$UID" -ne 0 ]; then
echo "Error! You are not a superuser. You have to run this script as superuser.";
exit $E_NOT_ROOT;
else
echo "Executing script to connect to Jalawave via bluetooth 3G modem.."
fi

#
# Check whether awk exists
#
if [ ! -x /usr/bin/awk ];then
echo "Error! Awk isn't installed. Aborting.."
exit 0
fi

#
# Check whether grep exists
#
if [ ! -x /usr/bin/grep ];then
echo "Error! Grep isn't installed. Aborting.."
exit 0
fi


#
# 2. Check whether rfcomm0 exists. If it isn't, then bind it
# using rfcomm.
echo "Configuring $COM_DEVICE.."

PHY_COM=$(ls /dev | grep $COM_DEVICE | awk '{print $1}')
if [ "$PHY_COM" != "$COM_DEVICE" ]; then
echo "$COM_DEVICE doesn't exist. Creating $COM_DEVICE.."

# Todo: handle other device(s) in the future
rfcomm bind $COM_DEVICE
fi

#
# 3. Check whether interface ppp0 exists. If it doesn't exist,
# execute "wvdial bluetooth" in the background and wait
# until ppp0 interface created.
#
PHY_PPP=$(ifconfig | grep $PPP_INTERFACE | awk '{print $1}')
if [ "$PHY_PPP" != "$PPP_INTERFACE" ]; then
echo "Executing wvdial in the background.."
wvdial bluetooth 2>/var/log/wvdial_log.txt &
echo "You can examine Wvdial output at /var/log/wvdial_log.txt"

# wait until the PPP device created
echo "Waiting for $PPP_INTERFACE to be created.."
while [ "$PHY_PPP" != "$PPP_INTERFACE" ]
do
PHY_PPP=$(ifconfig | grep '^ppp[0-9]' | awk '{print $1}')

# check whether the background wvdial process is still alive
WVDIAL_PS=$(ps -C wvdial | awk '{print $4}' | grep 'wvdial')
if [ "$WVDIAL_PS" != "wvdial" ]; then
echo "Wvdial terminated abruptly. Aborting.."
exit $E_WVDIAL_STOP
fi

# delay a little bit
sleep 1
done

else
echo "$PPP_INTERFACE interface exists as $PHY_PPP"
fi

#
# 4. Check whether the default gateway to Jalawave has been
# created by the route program. Create one if it's not
# been created yet.
#
echo "Checking for Jalawave gateway.."
MY_GW=$(route -n | awk '{print $2}' | grep $JALA_GW)
if [ "$MY_GW" != "JALA_GW" ]; then
echo "Jalawave gateway doesn't exist!"
echo "Creating default route to Jalawave gateway.."
route add default gw $JALA_GW $PPP_INTERFACE
echo "Default route created"
fi

#
# 5. Update the nameserver configuration to the right value
#
echo "Updating nameserver setting.."
cat /etc/ppp/resolv.conf > /etc/resolv.conf

echo "Connected."
exit 0


Of course this one still has a lot of bugs. I will refine it from time to time.
The second script is used to disconnect from the ISP.


#!/bin/bash
#
# This script suppose to disconnect from Jalawave
# The following is the logic.
# 1. Check whether the prerequisites are met.
# 2. Kill wvdial.
# 3. Wait for the ppp0 interface to be destroyed.
# 4. Release rfcomm0 binding.
#

# Error codes
E_NOT_ROOT=66 # Todo: you have to fix the error code

RFCOMM_DEVICE=rfcomm0
PPP_INTERFACE=ppp0

#
# 1. Check whether the prerequisite is met. Abort if it isn't.
#
if [ "$UID" -ne 0 ]; then
echo "Error! You are not a superuser. You have to run this script as superuser.";
exit $E_NOT_ROOT;
else
echo "Executing script to disconnect from Jalawave via bluetooth 3G modem.."
fi

#
# 2. Kill wvdial.
#

# check whether the background wvdial process is still alive
WVDIAL_PS=$(ps -C wvdial | awk '{print $4}' | grep 'wvdial')
if [ "$WVDIAL_PS" == "wvdial" ]; then
echo "Killing wvdial process.."
killall wvdial
fi

#
# 3. Wait until the PPP_INTERFACE destroyed before releasing
# rfcomm0 binding.
#

PHY_PPP=$(ifconfig | grep '^ppp[0-9]' | awk '{print $1}')

if [ "$PHY_PPP" == "$PPP_INTERFACE" ]; then
echo "Waiting for $PPP_INTERFACE to be destroyed.."
fi

while [ "$PHY_PPP" == "$PPP_INTERFACE" ]
do
PHY_PPP=$(ifconfig | grep '^ppp[0-9]' | awk '{print $1}')
sleep 1
done

#
# 4. Release rfcomm0 binding.
#
if [ -e "/dev/$RFCOMM_DEVICE" ]; then
echo "Releasing $RFCOMM_DEVICE binding.."
rfcomm release $RFCOMM_DEVICE
fi

echo "Disconnected."

exit 0

Monday, February 4, 2008

Upgrading from kernel 2.6.22.15 to 2.6.24

It's been a while I'm using Linux Slackware 12 with kernel 2.6.22.15. This was the most stable kernel version for my aging Compaq Presario W2718 laptop. It's also the one with most hardware features working as expected. Kernel 2.6.23 and its stable point releases (2.6.23.x) were not up to my expectation as they have problems in the sound drivers. I cannot get my laptop sound working reliably when using audacious, even though xine audio works just fine. I've upgraded my audacious to its latest version when using kernel 2.6.22.15 but it's still problematic and I found that quite a lot of people have the same problem with kernel 2.6.23.x releases. With the release of kernel 2.6.24 a few days ago, I have a chance to try upgrading my kernel once more. With a few hours testing as of now, it seems to be better than 2.6.22.15 that I use previously. Now, I have my Broadcom BCM4318 Wifi chip up and supposed to be working. I couldn't get it to work with the linux-wireless patch to kernel 2.6.22.15 -- Too bad I have no Wifi access point to test it against as of now :(. As for the Bluetooth, it seems to be working better than before.


To cut it short, here's how I upgraded from kernel 2.6.22.15 to 2.6.24:



  1. Download the needed patches from www.kernel.org or its ftp:

    • patch-2.6.22.15.bz2

    • patch-2.6.23.bz2

    • patch-2.6.24.bz2


  2. Decompress the patches:

    bzip2 -d -k [patch_file_name]



  3. Apply the patches to the kernel 2.6.22.15 source code by using the following commands in the root directory of the source code:

    patch -R -p1 < /path/to/patch/dir/patch-2.6.22.15
    patch -p1 < /path/to/patch/dir/patch-2.6.23
    patch -p1 < /path/to/patch/dir/patch-2.6.24

    Take a very close look that we are "reverse-patching" from 2.6.22.15 to 2.6.22 prior to "forward-patching" to kernel version 2.6.23. This is because the base kernel patch i.e., 2.6.x only applies to other 2.6.y kernel version. That's why you have to revert back to 2.6.22 before moving up to 2.6.23 and then to 2.6.24. Also note that the 2.6.x.y patches only applies to 2.6.x base kernel not to 2.6.x.w.

  4. Bake the new kernel

    make silentoldconfig
    make -j4

    Because I compiled on a faster machine, I do the following to pack the result and
    scp the result back to my laptop:

    make tarbz2-pkg
    [..scp the packed result to my laptop..]



  5. Test the new kernel.Hmmm... yummy.. >:). I've carried-out preliminary test on the kernel. Here's the result:
    • The bluetooth support is working better than ever

    • The wireless LAN support is still problematic, iwlist can display available network but dhclient or dhcpcd always fail. I'm using ndiswrapper and the Windows version of the WLAN driver instead. It works flawlessly but with the caveat that I have to disable all of the Broadcom BCM43xx related drivers in the kernel modules. I'll talk about it in the next point.



  6. Replace the native Linux 2.6.24 Broadcom BCM43xx driver with ndiswrapper and the Broadcom BCM43xx Windows XP driver. Here's how to do it:

    • Disable the BCM43xx native Linux driver by adding it into blacklist driver. To do so, edit /etc/modprobe.d/blacklist, add the following lines:

      # because we are using ndiswrapper driver for the network card, default
      # Broadcom BCM43xx and its corresponding drivers should not be loaded
      blacklist b43
      blacklist bcm43xx
      blacklist ssb


    • Compile and install ndiswrapper.

    • Install the Windows driver. I'm using the Broadcom BCM4318 driver that comes with my Compaq Presario W2718. The driver file is bcmwl5.sys and driver installation file is bcmwl5.inf.Place these files in one directory and run:

      bash-3$ ndiswrapper -i bcmwl5.inf

      Once the driver installation has been completed. Reboot the machine and then configure the interface with iwconfig. You scan the available accesspoints with
      iwlist wlan0 scanning

      and then to connect to one of the access point, set the essid with
      iwconfig wlan0 essid the_access_point_name

      and then obtain the ipaddress with
      dhcpcd wlan0
      or
      dhclient wlan0

      That's it, you should be online by now ;-).



  7. At this point, I'm stripping out every unneeded things from the kernel.
    To do that, trace sysfs for every used modules in the huge kernel and note
    them. Then look for them during kernel configuration, make sure to enable them.
    I'll talk about it later.



That's all for now. I'll keep posting my test results and other kernel works.

Sunday, January 20, 2008

Configuring Nokia E61 for ppp connection in Slackware 12

I wrote this because it takes me so long to get my Nokia E61 to work in Linux. The following are the problems that I faced and their solution. They are presented in order of resolving. Mind you that I'm using DKU-2 USB cable to connect my laptop with the Nokia E61 which acts as GPRS/3G modem.

Problem 1: The old firmware in my E61 is just not working in Linux at all (firmware version v2.0618.06.05). It doesn't respond to initialization commands other than the simpler ATZ variants, moreover, Wvdial version 1.60 always ended up with a segmentation fault. Therefore, I upgraded to firmware version 3.0633.09.04 to make wvdial works. I mean, with the new firmware, pppd that's called by wvdial can work up to displaying the CONNECT response. That's it, the old firmware is just not working properly. You have to use version 3.xx.xx.

Problem 2: The modem initialization command suggested by most people in the web is not working for me :(. I spent a day to find out how am I suppose to find the modem initialization command. Fortunately, as long as your Nokia E61 is working in Windows, you'll always found a working modem initialization command >:). It's located in the Windows installation directory, in my case, it's:

C:\WINDOWS\ModemLog Nokia E61 USB Modem #x.txt

Note that x denotes a number representing the USB port which the phone cable is connected to.

Below is snippet from the file in my laptop:

------- file: C:\WINDOWS\ModemLog_Nokia E61 USB Modem #2.txt ------------------
12-18-2007 16:03:20.000 - File: C:\WINDOWS\system32\tapisrv.dll, Version 5.1.2600
12-18-2007 16:03:20.000 - File: C:\WINDOWS\system32\unimdm.tsp, Version 5.1.2600
12-18-2007 16:03:20.000 - File: C:\WINDOWS\system32\unimdmat.dll, Version 5.1.2600
12-18-2007 16:03:20.015 - File: C:\WINDOWS\system32\uniplat.dll, Version 5.1.2600
12-18-2007 16:03:20.062 - File: C:\WINDOWS\system32\drivers\modem.sys, Version 5.1.2600
12-18-2007 16:03:20.062 - File: C:\WINDOWS\system32\modemui.dll, Version 5.1.2600
12-18-2007 16:03:20.062 - File: C:\WINDOWS\system32\mdminst.dll, Version 5.1.2600
12-18-2007 16:03:20.062 - Modem type: Nokia E61 USB Modem
12-18-2007 16:03:20.062 - Modem inf path: oem30.inf
12-18-2007 16:03:20.062 - Modem inf section: ModemDeviceInstallE61
12-18-2007 16:03:20.062 - Matching hardware ID: nmwcd\vid_0421&pid_044d&prot_00&if_mod_2k
12-18-2007 16:03:20.078 - 460800,8,N,1, ctsfl=1, rtsctl=2
12-18-2007 16:03:20.078 - Initializing modem.
12-18-2007 16:03:20.093 - Send: AT&F
12-18-2007 16:03:20.093 - Recv: AT&F
12-18-2007 16:03:20.093 - Command Echo
12-18-2007 16:03:20.093 - Recv: OK
12-18-2007 16:03:20.093 - Interpreted response: OK
12-18-2007 16:03:20.109 - Send: AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
12-18-2007 16:03:20.109 - Recv: AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
12-18-2007 16:03:20.109 - Command Echo
12-18-2007 16:03:20.109 - Recv: OK
12-18-2007 16:03:20.109 - Interpreted response: OK
12-18-2007 16:03:20.125 - Send: AT+IFC=2,2;+CVHU=1
12-18-2007 16:03:20.125 - Recv: OK
12-18-2007 16:03:20.125 - Interpreted response: OK
12-18-2007 16:03:20.140 - Send: ATS7=60+DS=3,0;&K3
12-18-2007 16:03:20.156 - Recv: OK
12-18-2007 16:03:20.156 - Interpreted response: OK
12-18-2007 16:03:20.156 - Sending user initialization commands.
12-18-2007 16:03:20.156 - Send: AT+CGDCONT=,,"jalawave.net.id"
12-18-2007 16:03:20.156 - Recv: OK
12-18-2007 16:03:20.156 - Interpreted response: OK
12-18-2007 16:03:20.156 - Waiting for a call.
12-18-2007 16:03:20.171 - Send: ATS0=0
12-18-2007 16:03:20.171 - Recv: OK
12-18-2007 16:03:20.171 - Interpreted response: OK
12-18-2007 16:03:20.171 - 460800,8,N,1, ctsfl=1, rtsctl=2
12-18-2007 16:03:20.187 - Initializing modem.12-18-2007 16:03:20.203 - Recv: OK
12-18-2007 16:03:20.203 - Interpreted response: OK
12-18-2007 16:03:20.203 - Send: AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
12-18-2007 16:03:20.203 - Recv: AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
12-18-2007 16:03:20.203 - Command Echo
12-18-2007 16:03:20.218 - Recv: OK
12-18-2007 16:03:20.218 - Interpreted response: OK
12-18-2007 16:03:20.218 - Send: AT+IFC=2,2;+CVHU=1
12-18-2007 16:03:20.218 - Recv: OK
12-18-2007 16:03:20.218 - Interpreted response: OK
12-18-2007 16:03:20.234 - Send: ATS7=60+DS=3,0;&K3
12-18-2007 16:03:20.234 - Recv: OK
12-18-2007 16:03:20.234 - Interpreted response: OK
12-18-2007 16:03:20.234 - Sending user initialization commands.
12-18-2007 16:03:20.250 - Send: AT+CGDCONT=,,"jalawave.net.id"
12-18-2007 16:03:20.250 - Recv: OK
12-18-2007 16:03:20.250 - Interpreted response: OK
12-18-2007 16:03:20.250 - Dialing.
12-18-2007 16:03:20.265 - Send: ATD*###
12-18-2007 16:03:22.765 - Recv: CONNECT
12-18-2007 16:03:22.765 - Interpreted response: Connect
12-18-2007 16:03:22.781 - Connection established at 460800bps.
12-18-2007 16:03:22.781 - Error-control off or unknown.
12-18-2007 16:03:22.781 - Data compression off or unknown.
12-18-2007 16:19:30.593 - Hanging up the modem.
12-18-2007 16:19:30.593 - Hardware hangup by lowering DTR.
12-18-2007 16:19:30.640 - Detected CD dropped from lowering DTR
12-18-2007 16:19:31.640 - Timed out waiting for response from modem
12-18-2007 16:19:31.656 - Send: ATH
12-18-2007 16:19:31.656 - Recv: OK
12-18-2007 16:19:31.656 - Interpreted response: OK
12-18-2007 16:19:31.656 - 460800,8,N,1, ctsfl=1, rtsctl=2
12-18-2007 16:19:31.656 - Initializing modem.
12-18-2007 16:19:31.671 - Send: AT&F
12-18-2007 16:19:31.671 - Recv: OK
12-18-2007 16:19:31.671 - Interpreted response: OK
12-18-2007 16:19:31.687 - Send: AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
12-18-2007 16:19:31.687 - Recv: AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
12-18-2007 16:19:31.687 - Command Echo
12-18-2007 16:19:31.687 - Recv: OK
12-18-2007 16:19:31.703 - Send: AT+IFC=2,2;+CVHU=1
12-18-2007 16:19:31.718 - Recv: OK
12-18-2007 16:19:31.718 - Interpreted response: OK
12-18-2007 16:19:31.734 - Send: ATS7=60+DS=3,0;&K3
12-18-2007 16:19:31.734 - Recv: OK
12-18-2007 16:19:31.734 - Interpreted response: OK
12-18-2007 16:19:31.734 - Sending user initialization commands.
12-18-2007 16:19:31.750 - Send: AT+CGDCONT=,,"jalawave.net.id"
12-18-2007 16:19:31.750 - Recv: OK
12-18-2007 16:19:31.750 - Interpreted response: OK
12-18-2007 16:19:31.750 - Waiting for a call.
12-18-2007 16:19:31.765 - Send: ATS0=0
12-18-2007 16:19:31.765 - Recv: OK
12-18-2007 16:19:31.765 - Interpreted response: OK
---------------------------------------------------------------------

Then, what to do with the information from this file? Yeah, I don't even have a clue at first.
But, I just thought there must be some lines which represent the "vendor specific" initialization
in it. After thinking for a while, I decided to add the following lines to my "partially working" wvdial.conf

Init1 = AT&F
Init2 = AT E0 V1 &D2 &C1 &S0 S0=0 +dr=1
Init3 = AT+IFC=2,2;+CVHU=1
Init4 = ATS7=60+DS=3,0;&K3
Init5 = AT+CGDCONT=1,"IP","jalawave.net.id"
Init6 = ATS0=0


Note: You have to add the correct Username and Password values in addition to the configuration values above to make it work.

Then I re-run wvdialconf. The resulting wvdial.conf is as follows:

----------------- file: /etc/wvdial.conf -----------------------------
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+IFC=2,2;+CVHU=1
Init4 = ATS7=60+DS=3,0;&K3
Init5 = AT+CGDCONT=1,"IP","jalawave.net.id"
Init6 = ATS0=0
Phone = *99#
Password = [my password]
Modem Type = USB Modem
Baud = 460800
New PPPD = yes
Dial Command = ATDT
Modem = /dev/ttyACM0
ISDN = 0
Username = [my login name]
-------------------------------------------------------------------------------------


After this changes, ppp is able to obtain a valid IP address and generates the correct DNS servers IP in /etc/ppp/resolv.conf. Below is a snippet from my shell when the connection is active.


bash-3.1# wvdial
--> WvDial: Internet dialer version 1.60
--> Cannot get information for serial port.
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
OK
--> Sending: AT+IFC=2,2;+CVHU=1
AT+IFC=2,2;+CVHU=1
OK
--> Sending: ATS7=60+DS=3,0;&K3
ATS7=60+DS=3,0;&K3
OK
--> Sending: AT+CGDCONT=1,"IP","jalawave.net.id"
AT+CGDCONT=1,"IP","jalawave.net.id"
OK
--> Sending: ATS0=0
ATS0=0
OK
--> Modem initialized.
--> Sending: ATDT*99#
--> Waiting for carrier.
ATDT*99#
CONNECT
~[7f]}#@!}!} } }2}#}$@#}!}$}%\}"}&} }*} } g}%~
--> Carrier detected. Waiting for prompt.
~[7f]}#@!}!} } }2}#}$@#}!}$}%\}"}&} }*} } g}%~
--> PPP negotiation detected.
--> Starting pppd at Tue Dec 18 17:38:30 2007
--> Pid of pppd: 4413
--> Using interface ppp0
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> local IP address 60.253.126.78
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> remote IP address 10.6.6.6
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> primary DNS address 202.51.232.114
--> pppd: È,ù·8‰[06][08](‰[06][08]
--> secondary DNS address 202.51.232.116
--> pppd: È,ù·8‰[06][08](‰[06][08]

Problem 3: The next thing to do is to set the default route in my Slackware 12 machine so that my browser and other network tools is working. To do that, I copied the DNS addresses from /etc/ppp/resolv.conf to /etc/resolv.conf. My /etc/resolv.conf then reads as:

---------------- file: /etc/resolv.conf ----------------------------------------------
nameserver 202.51.232.114
nameserver 202.51.232.116
-------------------------------------------------------------------------------------

Also, I set the default route using the ppp0 interface accordingly with the following command:


bash-3.1# route add default gw 10.6.6.6 ppp0


Voila', there you have it. Connecting to the Internet via a ppp connection with Nokia E61.

Anyway, I still have a few notes regarding the configuration of my current Slackware system:
======================================================
Kernel:

bash-3.1# cat /proc/version
Linux version 2.6.21.5-smp (root@midas) (gcc version 4.1.2) #2 SMP Tue Jun 19 14:58:11 CDT 2007

udev:

bash-3.1# udevinfo -V
udevinfo, version 111

=====================================================================
I need to note about this because I can't make my Nokia E61 works in Slackware 11 with a beefed-up kernel 2.6.23.1. Note that at the moment I'm using kernel 2.6.22.15 because the ATI AC'97 sound chip is problematic in kernel 2.6.23.x. Apparently, that's because of mismatch in the udev and kernel version. I'm still using the stock udev version 097 from kernel 2.6.17.3 (provided in Slackware 11 DVD) at that point. With an upgrade to Slackware 12 with udev 111. Everything is working as expected.


Using Nokia E61 GPRS/3G Modem Through Bluetooth Connection in Linux

In the previous explanation, the connection between the PC and Nokia E61 is through the supplied DKU-2 cable. In this section, I will explain how to use E61 as a GPRS/3G modem by using the bluetooth connection to connect the PC and E61. I'm using E61 with firmware version 3.0633.09.04 and Linux Slackware 12 (kernel updated to 2.6.23.12) with Bluez bluetooth stack. The steps are:

1. Install all the required bluetooth package. I'm using the bluetooth stack from the bluez project www.bluez.org. You can search your distribution for bluez utils package or download the latest from www.bluez.org

2. Make sure to turn on the bluetooth hardware in your E61 (Menu-->Connect-->Bluetooth).

3. Identify the bluetooth device indentifier of the modem in Linux. This is accomplished by using the hcitool, as follows:

bash-3.1 # hcitool inq
Inquiring ...
00:12:D1:85:E8:8F clock offset: 0x3950 class: 0x50020c
Line two shows the process of inquiring the bluetooth device (E61) for its bluetooth device id. The third line shows the result. The blutooth id for my particular E61 is 00:12:D1:85:E8:8F as shown above. This id is needed for the bluetooth configuration file (explained later).

4. Find out which "channel" is used by E61 in order to use it as a modem with sdptool. This is accomplised as follows:

bash-3.1# sdptool browse 00:12:D1:85:E8:8F
Browsing 00:12:D1:85:E8:8F ...
Service Name: AVRCP Target
Service Description: Audio Video Remote Control
Service Provider: Symbian Software Ltd.
Service RecHandle: 0x10000
Service Class ID List:
"AV Remote Target" (0x110c)
Protocol Descriptor List:
"L2CAP" (0x0100)
PSM: 23
"AVCTP" (0x0017)
uint16: 0x100
Profile Descriptor List:
"AV Remote" (0x110e)
Version: 0x0100

...truncated to save space...

Service Name: Dial-Up Networking
Service RecHandle: 0x10014
Service Class ID List:
"Dialup Networking" (0x1103)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 2
Language Base Attr List:
code_ISO639: 0x454e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Dialup Networking" (0x1103)
Version: 0x0100
...truncated to save space...

As you can see above, sdptool is used to browse the E61 by passing the E61 bluetooth address as one of its invocation parameter. The important thing to note is the channel used by the "Dial-up Networking" service in E61. As you can see clearly from sdptool browsing result, the channel used is channel 2. We need this information for the bluetooth configuration file.

5. Edit the bluetooth configuration file. The file is /etc/bluetooth/rfcomm.conf. The lines that start with a '#' are comments in this file. You have to use the information from step 3 and 4 above to complete this configuration file. The following is my configuration file:

#
# RFCOMM configuration file.
#
rfcomm0 {
# # Automatically bind the device at startup
# bind no;
#
# # Bluetooth address of the device
device 00:12:D1:85:E8:8F;

# # RFCOMM channel for the connection
channel 2;

# # Description of the connection
comment "Nokia E61 3G Modem via Bluetooth";
}

Note that each configuration line ends with a ';'. The address of the bluetooth device (E61) is the one that I call as bluetooth device id in step 3. Anyway, you can change the comment in the last line to whatever you like, but don't forget the trailing ';' in the end of the line ;-).

6. Edit the default "pass-code" for your bluetooth device. The pass code setting is in /etc/bluetooth/passkeys/default in my Slackware 12 Linux installation, yours may differ. This file is simply a text file that contains the pass code. I'm using "123" as the default pass code at one time to ease my burden ;-).

7. Now, restart the "bluetooth service" in Linux to activate the pass code. In my Slackware 12 installation I run the following command:

bash-3.1# /etc/rc.d/rc.bluetooth restart
At this point, your E61 should be asking for a passcode once it detected the bluetooth module in your PC. If you are using bluez tools, your PC should be detected as something like 'Bluez(0)' bluetooth device in your E61.

8. The last step is to "bind" your E61 as a modem. To do this, execute:

bash-3.1# rfcomm bind rfcomm0
Note that the command above, assumes that your E61 is configured as rfcomm0 interface in your bluetooth configuration file. It should be adapted to your present situation, i.e. prehaps you have another bluetooth device configured as rfcomm0. In that case then you have to adapt the command accordingly.

Now, your E61 should be present as a modem device in rfcomm0. You should be able to use it with Wvdial to connect to your ISP. Below, is my custom wvdial.conf for the bluetooth connection:

[Dialer bluetooth]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+IFC=2,2;+CVHU=1
Init4 = ATS7=60+DS=3,0;&K3
Init5 = AT+CGDCONT=1,"IP","jalawave.net.id"
Init6 = ATS0=0
Phone = *99#
Password = [ my password ]
Modem Type = USB Modem
Baud = 115200
New PPPD = yes
Dial Command = ATDT
Modem = /dev/rfcomm0
ISDN = 0
Username = [ my user name ]

I have no problem using my phone as a bluetooth GPRS/3G modem when using the above configuration. It should be OK for you too. To spoil the fun, I present the rather "obfuscated" connection log when using wvdial below >:).

bash-3.1# wvdial bluetooth
--> WvDial: Internet dialer version 1.60
--> Cannot get information for serial port.
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
OK
--> Sending: AT+IFC=2,2;+CVHU=1
AT+IFC=2,2;+CVHU=1
OK
--> Sending: ATS7=60+DS=3,0;&K3
ATS7=60+DS=3,0;&K3
OK
--> Sending: AT+CGDCONT=1,"IP","jalawave.net.id"
AT+CGDCONT=1,"IP","jalawave.net.id"
OK
--> Sending: ATS0=0
ATS0=0
OK
--> Modem initialized.
--> Sending: ATDT*99#
--> Waiting for carrier.
ATDT*99#
CONNECT
~[7f]}#@!}!} } }2}#}$@#}!}$}%\}"}&} }*} } g}%~
--> Carrier detected. Waiting for prompt.
~[7f]}#@!}!} } }2}#}$@#}!}$}%\}"}&} }*} } g}%~
--> PPP negotiation detected.
--> Starting pppd at Sun Dec 30 21:08:28 2007
--> Pid of pppd: 3022
--> Using interface ppp0
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> local IP address xx.xxx.xxx.xx
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> remote IP address xx.x.x.x
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> primary DNS address xxx.xx.xxx.xxx
--> pppd: È[1c]ù·°[06][08]À[06][08]
--> secondary DNS address xxx.xx.xxx.xxx
--> pppd: È[1c]ù·°[06][08]À[06][08]


The Windows vs Linux Bluetooth compatibility when using Nokia E61

After using my E61 as Bluetooth 3G Modem and switching to Linux kernel 2.6.22.15 which is the most stable and feature rich kernel for my machine right now, I found out that there's an issue using it as a 3G modem. The problem is mostly related to the Broadcom USB Bluetooth device after powering down the system or using my E61 in Windows and switching back to Linux. If I do one of those actions, the created rfcomm0 device always refuse to connect to the E61. After tinkering for a little while, I found out that the problems are due to:

  • An incompatibility between the Bluez utilities and the Kernel

  • Misconfiguration in /etc/wvdial.conf for bluetooth modem connection.

The first problem can be fixed by upgrading the problematic Bluez utilities to the latest version available in Slackware online repository (http://packages.slackware.it). Now, the Bluez utilities working as expected. I'm now using bluez-hcidump 1.40 (previously version 1.3x), bluez-libs 3.22 (the problematic one is bluez-libs 3.9), bluez-utils 3.22 (the problematic one is bluez-utils 3.9). Note that the bluez-firmware package doesn't have an update so I stuck with version 1.2.

The second problem can be fixed by fixing /etc/wvdial.conf. I didn't notice that there's one subtle difference between using E61 as USB modem and using it as bluetooth modem. The throughput of both mode are different, and it's reflected in the modem log file in Windows. I notice it when reading the following file:

------------- file: C:/WINDOWS/ModemLog_Bluetooth Modem.txt -------------
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\tapisrv.dll, Version 5.1.2600
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\unimdm.tsp, Version 5.1.2600
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\unimdmat.dll, Version 5.1.2600
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\uniplat.dll, Version 5.1.2600
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\drivers\modem.sys, Version 5.1.2600
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\modemui.dll, Version 5.1.2600
01-18-2008 12:32:38.909 - File: C:\WINDOWS\system32\mdminst.dll, Version 5.1.2600
01-18-2008 12:32:38.909 - Modem type: Bluetooth Modem
01-18-2008 12:32:38.909 - Modem inf path: oem49.inf
01-18-2008 12:32:38.909 - Modem inf section: Modemint
01-18-2008 12:32:38.909 - Matching hardware ID: {95c7a0a0-3094-11d7-a202-00508b9d7d5a}\wcbtmodem0
01-18-2008 12:33:02.206 - 115200,8,N,1, ctsfl=0, rtsctl=1
01-18-2008 12:33:02.206 - Initializing modem.
01-18-2008 12:33:02.206 - DSR is low while initializing the modem. Verify modem is turned on.
01-18-2008 12:33:02.206 - CTS is low while initializing modem.
01-18-2008 12:33:02.221 - Send: AT
01-18-2008 12:33:04.221 - Timed out waiting for response from modem
01-18-2008 12:33:04.221 - The modem failed to respond to the initialization command, Retrying one more time
01-18-2008 12:33:04.221 - 115200,8,N,1, ctsfl=0, rtsctl=1
01-18-2008 12:33:04.221 - DSR is low while initializing the modem. Verify modem is turned on.
01-18-2008 12:33:04.221 - CTS is low while initializing modem.
01-18-2008 12:33:04.237 - Send: AT
01-18-2008 12:33:06.237 - Timed out waiting for response from modem
01-18-2008 12:33:06.237 - The modem failed to respond to the initialization command, Retrying one more time
01-18-2008 12:33:06.237 - 115200,8,N,1, ctsfl=0, rtsctl=1
01-18-2008 12:33:06.237 - DSR is low while initializing the modem. Verify modem is turned on.
01-18-2008 12:33:06.237 - CTS is low while initializing modem.
01-18-2008 12:33:06.252 - Send: AT
01-18-2008 12:33:08.252 - Timed out waiting for response from modem
01-18-2008 12:33:08.252 - Lowering DTR before closing port
01-18-2008 12:33:08.362 - Session Statistics:
01-18-2008 12:33:08.362 - Reads : 0 bytes
01-18-2008 12:33:08.362 - Writes: 0 bytes


Notice the line that specify the baud rate of the Bluetooth modem above, it's only 115200, a lot slower compared to 460800 when using it as a USB Modem. After fixing the /etc/wvdial.conf to comply to this fact. I don't encounter any problem as previously.
I have adjust the bluetooth wvdial.conf section to reflect this change.

Further investigation shows that the fix I suggested above still not fixing the entire bluetooth problem. One more configuration must be fixed for the E61 to work seamlessly whether in Windows or Linux. The configuration involves giving the same device name for the hci device in both Windows and Linux. Note that the hci device is the bluetooth adapter in your machine which is in my case the Broadcom 2xxx bluetooth USB adapter. Why the name must be the same? It's because the of the pairing "cache" that the Nokia E61 stores in it's memory associates the bluetooth address of the hci device and its literal/alphanumeric name. If you use a different name in Linux and Windows, Nokia E61 will reject the connection next time you try to connect to it in Linux. I still don't know how the Windows driver for the bluetooth adapter forces Nokia E61 to "flush" its pairing "cache" when I reboot to Windows from Linux. Anyway, you have to edit the /etc/bluetooth/hcid.conf file and make the device name identical to the name displayed in your Nokia E61 when you try to pair it in Windows. In my case, the name is PINCZAKKO. Therefore, I edit /etc/bluetooth/hcid.conf to change the default name. The final /etc/bluetooth/hcid.conf as follows:

#
# 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 user;

# 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
passkey "BlueZ";
}

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

# Local device class
class 0x000100;

# 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;
}

Notice the bold line where I change the name of the hci device to PINCZAKKO. I have one thing left to be figured out, how the Windows driver and/or application set the name for the Broadcom bluetooth USB adapter? In the mean time, I'll conduct more tests.


I hope you can configure your E61 bluetooth connection flawlessly as well ;-).
Have fun.



Final note
===========
  • Mind you that this is a work-in-progress notes. So, I'll update this post as soon as I have time.
  • There's an excellent free book about Linux kernel that I think is a must read. The title is Linux Kernel In a Nutshell, you can download it freely at: http://www.kroah.com/lkn/
  • Pay more attention to see the device capabilities when you configure the device, so that you don't do silly misconfiguration as what I did with the bluetooth 3G modem of my Nokia E61 (sic)

Thursday, December 20, 2007

Setting up Your Linux Desktop for Blackfin BF-537 STAMP Board Development

In this post, I will provide a step-by-step guide to prepare your linux desktop for blackfin BF-537 STAMP board software development.

The first thing to do, is to ensure that you have everything that you will need installed correctly in your system. The things that you need are explained below.

The Hardware side.

1. A development machine. In this article I will refer to x86-based development machine exclusively. We will call this development machine as development PC. Later you will see that this choice will affect the type of cross-compiling tool that we will use during the development.

2. A serial connector that connects the development machine and the blackfin BF-537 STAMP board. If you have a physical serial port (DB-9) in your development PC, using the serial port is straight forward. However, if you don't have one (as is the case of most contemporary x86 machines), you will need to use usb-to-serial converter to connect the development machine and the BF-537 STAMP board. I will explain the implication of using a usb-to-serial converter in the software side of things in Linux later.

3. A twisted-pair ethernet cable. This cable is not mandatory. Nonetheless, you will find it difficult to do the data transfer between the development PC and BF-537 STAMP board without it. The data transfer would practically too slow if you are only using the serial connection. Therefore, it's strongly suggested to prepare it to connect the development PC and the BF-537 board. In this article, we will assume that such an ethernet connection exists.

The Software Side.

1. A working linux kernel that can access the serial port in your develpment PC. If you are using a usb-to-serial converter, it's better to use Linux with kernel 2.6.xx and udev version 0.97 or higher because the support for dynamic /dev/ttyUSBx creation is very good. Previous kernel versions probably work out-of-the-box but I cannot assure you because I haven't tested them. Note that if you are using kernel 2.6.xx, the udev version must be compatible with the kernel version. Otherwise, the dynamic /dev/ttyUSBx creation might not be working properly. You might want to read the Linux Serial HOWTO if you are using older kernel version. In my system setup, I use Slackware 12 with kernel version 2.6.21.5 and udev version 111. I'm using a USB-to-serial converter based on the Prolific PL2303 chip which is supported natively in this kernel.

2. A terminal application to communicate with the serial port. In my setup, I use Minicom as the terminal application. Minicom is easy to setup, just run it with '-s' argument to setup everything upon starting, like this:
bash-3.1 $ minicom -s
This will prevent minicom from exiting abruptly if it encounter error upon invocation. With the '-s' argument, Minicom will display the following configuration screen.

In this configuration screen, there are two items that must be configured. The first one is the 'Serial port setup' and the second one is the 'Modem and dialing'. In the serial port setup, choose the right setting for the serial device. Press 'A' to navigate to the Serial Device setup, then edit the /dev/ttyXXX to reflect your current system setup. If you are using a USB-to-serial converter, your serial device probably /dev/ttyUSB0, do a 'lsusb' and 'dmesg | grep usb' to find out. Next, press 'E' to navigate to Bps/Par/Bits. This is the bit rate, parity and stop-bit setting, set it to 57600 8 N 1. Then, press 'F' and set the Hardware Flow Control to No and then press 'G' and set the Software Flow Control to No.

The next thing to configure is the 'Modem and dialing' options. Basically, we don't want minicom to regard our serial device as ordinary modem device. Therefore, we have to clear all modem specific settings. To do so, from the serial port setup, press 'Esc' to go back to main Minicom setup screen and then choose 'Modem and dialing'. The following screen will be shown.

In the Modem and Dialing setting, set everything to nothing, starting from option A (Init string) until connect string. This will remove unnecessary initialization code that will be sent to the modem (i.e. the Blackfin STAMP) when minicom starts.

3. A tftp server in the development machine. The tftp server is used by the Blackfin STAMP as the source of the uClinux binary image when it boots. The Blackfin STAMP will issue a tftp "boot image request" when it boots, the tftp server in the development PC will serve the request by transfering the "boot image" according to the setting of the tftp server. Now, I will present you with the setting for Slackware 12. This setting is also working in Slackware 11. Before starting with the configuration, make sure you have installed the tftp package. The tftp server in Slackware is tftpd, which is controlled by /etc/inetd.conf script. By default, the tftp server is disabled. To activate the server, edit /etc/inetd.conf script. In that file you should find the following lines:

# See "man 8 inetd" for more information.
#
# If you make changes to this file, either reboot your machine or send the
# inetd a HUP signal:
# Do a "ps x" as root and look up the pid of inetd. Then do a
# "kill -HUP "
# The inetd will re-read this file whenever it gets that signal.
#
#
# ... irrelevant lines omitted
#
# Tftp service is provided primarily for booting. Most sites
# run this only on machines acting as "boot servers."
tftp dgram udp wait root /usr/sbin/in.tftpd in.tftpd -s /tftpboot -r blksize
#
# ... irrelevant lines omitted
The tftpd has been activated in the modified file above, the comment ('#') has been removed. You can check whether the tftpd server has been running or not with 'netstat -a' command. If everything is OK, your shell should report something like this:

bash-3.1# netstat -a | more
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:time *:* LISTEN
tcp 0 0 *:x11 *:* LISTEN
tcp 0 0 *:auth *:* LISTEN
tcp6 0 0 *:ssh *:* LISTEN
udp 0 0 *:biff *:*
udp 0 0 *:time *:*
udp 0 0 *:tftp *:*
...

The last line in the shell dump above shows that the tftp server is active and uses UDP to serve its clients. In UDP connection there's no such a 'LISTEN' state which exists for TCP connection.

Anyway, as you can see in the tftp invocation, the /tftpboot directory is specified as the default directory used by the tftp client machine to search for boot image(s). Therefore, we should place the boot image file(s) there. You can change the default boot directory if you wish, however, pay attention to adapt the tftp invocation command as well. Now, everything is in place the next step is to place the boot image in /tftpboot directory. The firmware in Blackfin STAMP board will look for a boot image file named 'linux'. Therefore you should rename the image (binary file) that you intend to use booting the board into 'linux' and place it in /tftpboot directory or whatever directory that you have specified in /etc/inetd.conf.

There you have it. You can now connect your Blackfin STAMP board through the serial cable and download the boot image through the Ethernet connection. Mind you that you have to setup the Blackfin STAMP IP in advance whether by DHCP or static IP to be able to boot the image that is stored in the directory specified by the tftp server in your development PC. Below is a sample screenshot when the Blackfin STAMP successfully boot the board through the Ethernet connection. This screenshot is taken from minicom that runs in the console.


4. The Blackfin uClinux toolchain. The toolchain can be downloaded at http://blackfin.uclinux.org/gf/project/toolchain/frs/. Pay attention to the toolchain type. Because we are assuming that you are running a 32-bit x86 Linux desktop, then the toolchain that will be used is the blackfin-toolchain-07r1.1-3.i386.tar.gz or its RPM version. If you are using another version of Linux, e.g. x86_64, you must download the appropriate toolchain. Configuring and installing the toolchain is outside the scope of this article as the toolchain distribution has provided the required information.


Miscellaneous Troubleshooting Guide
-----------------------------------------------------
(*) If you have problems connecting the PC and the Blackfin STAMP through Ethernet, the first step you have to do is to check the physical Ethernet connection between your development PC and the Blackfin STAMP. You can do this easily by seeing whether the LED indicator in the RJ-45 connector at both ends (on the Blackfin STAMP and on the PC) are on or off when idle. If they are off, it means there's something wrong with your physical Ethernet connection, you have to fix it. Otherwise the connection is just fine. The problem that arise sometimes is caused by the Ethernet cable or the RJ-45 connector in one end that get loose.

(*) The following steps might be helpful if you have problems with the serial connection when using a USB-to-serial converter.
a. Check whether the correct usb kernel modules are loaded. You will need the usbserial module and the particular USB-to-serial converter chip module which in my case is the pl2303 module. Below is a snippet from my system.

bash-3.1# lsmod
Module Size Used by
...<>...
pl2303 22404 1
...<>...
usbserial 33384 3 pl2303
...<>...


b. Check whether the USB converter chip is detected by your Linux machine, as follows:
bash-3.1# lsusb
Bus 001 Device 001: ID 0000:0000
Bus 003 Device 001: ID 0000:0000
Bus 002 Device 004: ID 0a5c:2100 Broadcom Corp.
Bus 002 Device 003: ID 0a5c:4500 Broadcom Corp.
Bus 002 Device 002: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Bus 002 Device 001: ID 0000:0000
The command lsusb will list all of the connected USB hardware in your PC. In the shell dump above, you can see that my USB-to-serial converter chip is based on Prolific PL2303 chip. You can find out about supported USB-to-serial in the kernel source the Documentation/usb/usb-serial.txt. If the chip is detected but you still have problem. Try the next step.

c. Check whether there is a terminal device created for your USB-to-serial converter. If the converter is working properly, you should see a /dev/ttyUSBx device in your /dev directory. x in ttyUSBx denotes a number, starting from 0 which indicates the number for the available USB-to-serial "terminal". In my system, it's as follows:
bash-3.1$ ls /dev/ttyUSB*
/dev/ttyUSB0

In some buggy kernel + udev pair, the ttyUSBx device node won't be created automatically. In that case, you have to create it manually with mknod and major number for the character device is 188 and minor number depending on how many usb-to-serial modules have been attached. For example, if there's only one usb-to-serial converter, then you will invoke:

mknod /dev/ttyUSB0 c 188 0

The '0' in the end of the command above denotes that this is the first USB-to-serial convertern in your system.


TODO: Optional Configurations
--------------------------------------
4. An ftp server in the development machine (optional).

5. A dhcp server in the development machine (optional).