This article is a first pass at how to get a Bluetooth GPS working with the default Xandros OS in advanced desktop mode.
When the modifications are complete, you will be able to:
Once you get through setting things up the first time, there will be no need to open up a console terminal to enable/configure/disable anything.
Here's the theory of how this works: the Eee detects when you plug a device into a USB port. udev runs through a set of rules looking for a matching device. If you've plugged in a Bluetooth adapter that it recognizes, it runs a script to configure it. The script enables the Bluetooth adapter, configures a serial device to attach to the Bluetooth GPS, and starts up the gpsd program. gpsd takes care of accepting the GPS position information from the Bluetooth GPS and parceling it out to any gpsd clients that request it.
Install the gpsd package. The gpsd-clients package isn't necessary, but would be handy for making sure that you have gpsd running if you don't have any other gpsd aware GPS programs installed.
Start udevmonitor and plug your Bluetooth adapter in.
vesta:/root> udevmonitor udevmonitor prints the received event from the kernel [UEVENT] and the event which udev sends out after rule processing [UDEV] UEVENT[1202492249.970587] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2 UEVENT[1202492249.970671] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/usbdev1.5_ep00 UEVENT[1202492249.970691] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.0 UEVENT[1202492249.970709] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.0/hci0 UEVENT[1202492249.970726] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.0/usbdev1.5_ep81 UEVENT[1202492249.970743] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.0/usbdev1.5_ep02 UEVENT[1202492249.970760] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.0/usbdev1.5_ep82 UEVENT[1202492249.970778] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.1 UEVENT[1202492249.970795] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.1/usbdev1.5_ep03 UEVENT[1202492249.970812] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.1/usbdev1.5_ep83 UEVENT[1202492249.970830] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2:1.2 UEVENT[1202492249.970847] add@/devices/pci0000:00/0000:00:1d.0/usb1/1-2/usbdev1.5
The line of interest in my case was the second from the last. The one you use end up using may be different. I started off using the first line, but soon discovered that that caused my udev rules to run four times.
(I think I know why this is, but I don't know enough about udev to say for certain.) Anyhow, copy the text from the appropriate line starting after the '@' all the way to the end of the line and paste it onto the end of a command line for udevinfo, like so:
vesta:/root> udevinfo -a -p /devices/pci0000:00/0000:00:1d.0/usb1/1-2:1.2
udevinfo starts with the device the node belongs to and then walks up the
device chain, to print for every device found, all possibly useful attributes
in the udev key format.
Only attributes within one device section may be used together in one rule,
to match the device for which the node will be created.
looking at device '/devices/pci0000:00/0000:00:1d.0/usb1/1-2:1.2':
KERNEL=="1-2:1.2"
SUBSYSTEM=="usb"
SYSFS{modalias}=="usb:v1131p1001d0373dcE0dsc01dp01icFEisc01ip00"
SYSFS{bInterfaceProtocol}=="00"
SYSFS{bInterfaceSubClass}=="01"
SYSFS{bInterfaceClass}=="fe"
SYSFS{bNumEndpoints}=="00"
SYSFS{bAlternateSetting}==" 0"
SYSFS{bInterfaceNumber}=="01"
looking at device '/devices/pci0000:00/0000:00:1d.1/usb2/2-1':
ID=="2-1"
BUS=="usb"
DRIVER=="usb"
SYSFS{product}=="ISSCEDRBTA"
SYSFS{manufacturer}=="ISSC"
SYSFS{quirks}=="0x0"
SYSFS{maxchild}=="0"
SYSFS{version}==" 1.10"
SYSFS{devnum}=="3"
SYSFS{speed}=="12"
SYSFS{bMaxPacketSize0}=="16"
SYSFS{bNumConfigurations}=="1"
SYSFS{bDeviceProtocol}=="01"
SYSFS{bDeviceSubClass}=="01"
SYSFS{bDeviceClass}=="e0"
SYSFS{bcdDevice}=="0373"
SYSFS{idProduct}=="1001"
SYSFS{idVendor}=="1131"
SYSFS{bMaxPower}==" 0mA"
SYSFS{bmAttributes}=="c0"
SYSFS{bConfigurationValue}=="1"
SYSFS{bNumInterfaces}==" 3"
SYSFS{configuration}==""
looking at device '/devices/pci0000:00/0000:00:1d.0/usb1':
.
.
.
and so on, and so on...
Although there's an awful lot of text, we're only interested in a few lines that are very close to the top. Find the lines that start with KERNEL, SYSFS{idProduct} and SYSFS{idVendor}. You'll need the values from the lines in a bit, so write them down. For the purposes of this discussion, we'll use the values I got from my adapter.
KERNEL=="1-2:1.2"
SYSFS{idProduct}=="1001"
SYSFS{idVendor}=="1131"
Repeat the process by plugging the adapter into each remaining USB port on the eee. The only thing that should change is the KERNEL value.
: there's got to be a way to do this only once!
Since the adapter is plugged in, now is a good spot to grab some necessary information about your Bluetooth GPS as well. Turn your GPS on and we'll bring the interface up and use hcitool to scan for nearby Bluetooth devices.
vesta:/root> hciconfig hci0 up
vesta:/root> hcitool scan
Scanning ...
00:0D:35:B5:3A:DA BT-GPS-354ADA
00:1E:36:71:8D:AD CTERRY-LAPTOP
Your output will be different of course, but somewhere in there you should be able to see a line identifying itself as a GPS. Record the contents of this line for later. Remove your adapter for the moment.
Amongst other things, installing gpsd created some files that have to be modified to get everything starting up and shutting down automatically. We'll begin with /etc/udev/gpsd.rules.
Right after the comment lines at the start of the file, add the following line:
SUBSYSTEM!="tty", GOTO="gpsd_rules_usb"
After the last line, add the following lines, replacing my values for KERNEL, SYSFS{idVendor} and SYSFS{idProduct} with the ones you got:
LABEL="gpsd_rules_usb"
SUBSYSTEM!="usb", GOTO="gpsd_rules_end"
# GXT (ValGear) Bluetooth USB adapter
ACTION=="add", KERNEL=="1-2:1.2", SUBSYSTEM=="usb", SYSFS{idVendor}=="1131", SYSFS{idProduct}=="1001", RUN+="/lib/udev/gpsd.rfcomm"
ACTION=="add", KERNEL=="2-1:1.2", SUBSYSTEM=="usb", SYSFS{idVendor}=="1131", SYSFS{idProduct}=="1001", RUN+="/lib/udev/gpsd.rfcomm"
ACTION=="add", KERNEL=="2-2:1.2", SUBSYSTEM=="usb", SYSFS{idVendor}=="1131", SYSFS{idProduct}=="1001", RUN+="/lib/udev/gpsd.rfcomm"
ACTION=="remove", KERNEL=="1-2:1.2", RUN+="/lib/udev/gpsd.rfcomm"
ACTION=="remove", KERNEL=="2-1:1.2", RUN+="/lib/udev/gpsd.rfcomm"
ACTION=="remove", KERNEL=="2-2:1.2", RUN+="/lib/udev/gpsd.rfcomm"
LABEL="gpsd_rules_end"
You can see where the values for KERNEL, SYSFS{idVendor} and SYSFS{idProduct} were inserted. Save the file and reload the rules.
vesta:/root> udevcontrol reload_rules
At this point, if you were impatient enough to plug in your Bluetooth adapter, the add rule you just added would be activated and would try and run the script /lib/udev/gpsd.rfcomm. Of course it doesn't exist yet, so let's create that script now.
#!/bin/sh
if [ "$ACTION" = "remove" ] ; then
/lib/udev/gpsd.hotplug remove /dev/rfcomm0
rfcomm release /dev/rfcomm0
hciconfig hci0 down
if [ -e "dev/rfcomm0" ] ; then
rm /dev/rfcomm0
fi
else
rfcomm release /dev/rfcomm0
sleep 0.5
if [ -e "dev/rfcomm0" ] ; then
rm /dev/rfcomm0
fi
hciconfig hci0 up
sleep 0.5
rfcomm bind /dev/rfcomm0
sleep 0.5
chmod 666 /dev/rfcomm0
exec /lib/udev/gpsd.hotplug add /dev/rfcomm0
fi
Don't forget to make the script executable.
chmod 755 /lib/udev/gpsd.rfcomm
What does this do? When you plug your Bluetooth adapter in, the script will be called with the variable ACTION set to add. It falls through to the else clause and begins by trying to get rid of any leftover /dev/rfcomm0 file. I had problems with this when I was figuring things out and it probably could be removed now, but it works as is and doesn't do any damage. Next, it brings the interface to the Bluetooth adapter up and creates a new /dev/rfcomm0 file (making it read/write accessible to the world). Finally it informs gpsd that there's a new GPS available that it can talk to.
When the adapter is removed, the process essentially works in reverse. It begins by informing gpsd that the GPS is no longer available, removes the serial device that gpsd was talking to, and brings the Bluetooth adapter's interface down. The last step is really not necessary (the system is going to remove the interface anyway when you remove the adapter). In a final bit of leftover developmental paranoia, we attempt to delete any leftover /dev/rfcomm0 file.
There's a skeleton configuration file for rfcomm installed by default at /etc/bluetooth/rfcomm.conf. We need to modify it so that /dev/rfcomm0 is associated with your particular GPS. Edit the file so that it looks like the following, replacing the device and comment strings with what you saw when you ran 'hcitool scan'.
#
# RFCOMM configuration file.
#
rfcomm0 {
# Automatically bind the device at startup
bind yes;
# Bluetooth address of the device
device 00:0D:35:B5:3A:DA;
# RFCOMM channel for the connection
channel 1;
# Description of the connection
comment "BT-GPS-354ADA";
}
Now we need to add a couple of modules to the list of modules that get loaded when the system starts up. You could skip this part, but then you'd have to plug your adapter in twice the first time after powering up in order to get everything to work. Edit /etc/modules and add the following two lines to the end of the file:
hci_usb rfcomm
That's it for the file modifications. Reboot your system to make sure that all the changes take effect properly, plug your Bluetooth adapter in and turn your GPS on. If you installed the gpsd-clients package, you can start up xgps and you should see your GPS data.