GPSd and the HP un2420

At a recent radio club technical night we ran through the setup of ntpd and GPSd for time syncing laptops. This is important when running modes like FT8 and JT65 where transmissions are synchronised to the nearest second, or for satellite tracking.

Picture of HP2420 Modem

During the tech night we used a external USB GPS, however my laptop has a HP un2420 broadband modem inside that includes a built in GPS. So after the tech night I decided to see if I could get GPSd to work with this module.

In a previous post I found that you could send a string to the last of three USB serial ports that this module creates [ttyUSB0-2], that would then activate the GPS functions within the module you can read this here (click).

So to use this module we need GPSd to send a “\$GPS_START” string to the GPS before it tries to use it. It also needs to send a “\$GPS_STOP” string to the GPS when GPSd stops.

It turns out GPSd has internal mechanisms to do this via a device-hook that you can find in the man page, however there aren’t many examples of “how” to do this on the internet.

The device hook file is nothing more than a simple bash script that is called by GPSd as it starts or stops the GPSd service. It will call this bash script using two parameters, the first is the name of the device, the second is the action required i.e.”activated” or “deactivated”. So all we need is a basic script, there are probably more elegant ways to write this script than what I’ve used, but it works for me.

So using your favourite editor create the file below with the following contents;

/etc/gpsd/device-hook

#!/bin/bash
#
#device hook script to start and stop HP2420 internal GPS
#
if [ "$1" = "/dev/ttyUSB2" ] && [ "$2" = "ACTIVATE" ];
then
echo "\$GPS_START" > "/dev/ttyUSB2"
sleep 5
else
if [ "$1" = "/dev/ttyUSB2" ] && [ "$2" = "DEACTIVATE" ];
then
echo "\$GPS_STOP" > "/dev/ttyUSB2"
fi
fi

This script simply matches the USB serial device the HP un2420 creates with the word ACTIVATE and fires the magic string into the USB serial device and will return 0 to GPSd. The same happens when GPSd wishes to stop the GPS device. These internal GPS devices do not like starting then immediately stopping, it can bork the device to the point it requires the laptop to be rebooted. So to prevent this a short sleep delay has been added just after we activate the GPS. I could have equally added it after or before the STOP command, but this might not be a good idea as laptops have a tendency to hibernate and we would like the GPS to stop.

Now that we have our script we need to make sure it’s executable by GPSd. I found that if you start GPSd and don’t let it daemonise for debugging, it will tell you which user and group that it starts with, we just need to make our permissions match;

$ sudo gpsd -N -D3 -F /var/run/gpsd.sock /dev/ttyUSB2
gpsd:INFO: launching (Version 3.17)
gpsd:INFO: listening on port gpsd
gpsd:INFO: stashing device /dev/ttyUSB2 at slot 0
gpsd:INFO: running with effective group ID 20
gpsd:INFO: running with effective user ID 122

gpsd:INFO: startup at 2019-03-07T23:52:07.000Z (1552002727)

I’ve highlighted the two lines we’re looking for. We can go and match these ID numbers to the specific user and group in the /etc directory. If you press Ctrl-C then GPSd will stop. Looking at the ID’s on my laptop this was user ‘gpsd’ and group ‘dialout’, YMMV.

So now we can set the right owner and permissions for our device-hook file;

$ sudo chown root:dialout /etc/gpsd/device-hook
$ sudo chmod 750 /etc/gpsd/device-hook
$ ls
legend@HP-ProBook:/etc/gpsd$ ls -al
total 20
drwxr-xr-x   2 root root     4096 Mar  8 09:54 .
drwxr-xr-x 130 root root    12288 Mar  8 00:06 ..
-rwxr-x---   1 root dialout   280 Mar  8 09:54 device-hook

Basically owner is left as root and we’ve given read and execute permissions to group dialout. This will allow GPSd to read the file and only sudo users able to edit it.

So using the same command line as before start GPSd in a window. Now in a second window launch a client like cgps. In the GPSd window we should see something like this;

legend@HP-ProBook:$ sudo gpsd -N -D3 -F /var/run/gpsd.sock /dev/ttyUSB2
gpsd:INFO: launching (Version 3.17)
gpsd:INFO: listening on port gpsd
gpsd:INFO: stashing device /dev/ttyUSB2 at slot 0
gpsd:INFO: running with effective group ID 20
gpsd:INFO: running with effective user ID 122
gpsd:INFO: startup at 2019-03-07T23:52:07.000Z (1552002727)
gpsd:CLIENT: => client(0): {"class":"VERSION","release":"3.17","rev":"3.17","proto_major":3,"proto_minor":12}\x0d\x0a
gpsd:CLIENT: <= client(0): ?WATCH={"enable":true,"json":true};\x0a
gpsd:INFO: running /etc/gpsd/device-hook /dev/ttyUSB2 ACTIVATE
gpsd:INFO: /etc/gpsd/device-hook returned 0

gpsd:INFO: SER: opening GPS data source type 3 at '/dev/ttyUSB2'
gpsd:INFO: SER: speed 9600, 8N1
gpsd:INFO: attempting USB device enumeration.
gpsd:INFO: 8087:0020 (bus 2, device 2)
gpsd:INFO: 1d6b:0002 (bus 2, device 1)
gpsd:INFO: 05c8:0403 (bus 1, device 4)
gpsd:INFO: 03f0:251d (bus 1, device 8)
gpsd:INFO: 8087:0020 (bus 1, device 2)
gpsd:INFO: 1d6b:0002 (bus 1, device 1)
gpsd:INFO: vendor/product match with 091e:0003 not found
gpsd:INFO: SER: speed 9600, 8O1
gpsd:INFO: SER: speed 9600, 8N1
gpsd:INFO: SER: speed 9600, 8N1
gpsd:INFO: SER: speed 9600, 8N1
gpsd:INFO: gpsd_activate(2): activated GPS (fd 8)

< BIG SNIP>

^Cgpsd:WARN: received terminating signal 2.
gpsd:INFO: closing GPS=/dev/ttyUSB2 (8)
gpsd:INFO: running /etc/gpsd/device-hook /dev/ttyUSB2 DEACTIVATE
gpsd:INFO: /etc/gpsd/device-hook returned 0

gpsd:WARN: exiting.

The two lines we need to find I’ve highlighted above. Basically we want to see GPSd execute our script with a return value of 0 (success). I’ve snipped a sizeable amount of information out of the above window to make it more readable. You should also see where I’ve hit Ctrl-C which generates a warning to cgps that GPSd has shutdown, which is neat !

Ok so now we have GPSd starting and stopping the GPS device in my laptop correctly. However this is not the end of the story, laptops are able to be suspended so we need to take care of this as well. So using your favourite editor create/edit the following file;

/etc/pm/sleep.d/96_gpsd

#!/bin/bash
#
# what we want done with our GPS in the laptop
case "$1" in
hibernate)
#stop GPSd
systemctl stop gpsd.socket
systemctl stop gpsd
;;
suspend)
#stop GPSd
systemctl stop gpsd.socket
systemctl stop gpsd
;;
restart)
#restart GPSd
systemctl restart gpsd
;;
esac

Thankfully as soon as we tell GPSd to stop it calls /etc/gpsd/device-hook and DEACTIVATES the GPS module for us. Now we also need to set the permissions correctly;

legend@HP-ProBook:/etc/pm/sleep.d$ chmod 755 96_gpsd
legend@HP-ProBook:/etc/pm/sleep.d$ ls -al
total 20
drwxr-xr-x 2 root root 4096 Mar  8 11:09 .
drwxr-xr-x 3 root root 4096 Apr 27  2018 ..
-rwxr-xr-x 1 root root  273 Mar  8 11:09 96_gpsd

Testing of this script is as simple as calling it with the correct first parameter. Testing that our distros are calling this file is a little harder and may be the subject of yet another post. I’m thinking that I need to measure if there is a performance difference with the GPS running while hibernated or not, this sounds easy but will take many hours. Still pondering.

There we go, the internal GPS within the un2420 should now be available, it would be worth rebooting your machine to make sure everything is working well.

HP Cellular Modem for HP 5320m

After pulling the bottom cover off my second-hand HP Probook 5320m a couple of times I was pleased to discover a PCI-E slot for a HP un2420 mobile broadband modem.  It appears that the Cellular antennas are already built within the lid (or screen) of the laptop.   A light bit of reading also suggested that these modules were capable of decoding GPS signals too.

I just had to try one.

So for the princely sum of $35 I procured a HP un2420 Gobi 2000 module from a local eBay seller.  There are suppliers on eBay that are selling these HP Gobi 2000 modems out of China for $11, which is an absolute bargain. YMMV.  I didn’t want to wait until after Christmas to try one so I purchased one at the higher price.

Now of course I want this to work in my shiny new Ubuntu 16.04 LTS laptop.  Oh well I’ve always welcomed a challenge.   I’ll detail the steps I took to get to a working solution.

First we should check we can see the module;

#$ lsusb
Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 05c8:0403 Cheng Uei Precision Industry Co., Ltd Webcam
Bus 001 Device 003: ID 03f0:241d Hewlett-Packard Gobi 2000 Wireless Modem
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

I’ve highlight what we’re looking for (in blue) which is the “HP Gobi 2000 wireless modem”.  You can tell that this device is currently un-programmed as the product ID is “241d” and changes to “251d” once the firmware is loaded.   You also need to check that /dev/ttyUSB0 exists and that your user that starts the 3G cellular modem is in group dialout.  This isn’t necessary right now but does simplifies things later.

Now you’re going to require a Microsoft Windows machine, sorry there is no other easy way around this.  Some have managed to pull apart MSI files in wine, I didn’t get that lucky.  The Qualcomm Gobi modems down load the firmware into the modem at power on, once the firmware has been download the modems will work.   I was lucky to have the same laptop with Windows 10 installed, so I simply installed the driver on this second machine and then stole the files I needed on a USB stick.  I had to install the un2420 module in the Windows machine to get the drivers to load.

From within the Windows driver there are two directories from which we need three files;

  • ….\Qualcomm\Images\HP\UMTS\amss.mbn
  • ….\Qualcomm\Images\HP\UMTS\apps.mbn
  • ….\Qualcomm\Images\HP\6\uqcn.mbn

You’ll need to work out where the drivers get placed depending on your version of windows, it will be installed in the program directories there somewhere.  I found them in the Program Files (x86) directory on Windows 10.   The files above are what you require for a Generic UMTS modem (6) that is not vendor network specific or locked.  This worked nicely for my unlocked module and Telstra pre-paid SIM. YMMV.

Now once you have these files on a USB stick you can start work on the Linux machine.

#$ sudo apt-get install gobi-loader

This will get the udev helper we need to load the firmware into the modem.  Once this is installed copy the files from the windows machine into this directory, watching file permissions of course;

#$ sudo cp /mnt/usbstick/* /lib/firmware/gobi

As mentioned we want all three “mbn” files above in that directory.  Now you might like to check that the udev rules for QDL modems are correct in the following file;

#$ less /lib/udev/rules.d/77-mm-qdl-device-blacklist.rules

Your looking to check that the following two lines exist;

#HP un2420 Gobi QDL Device
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=='241d", \ ENV{ID_MM_DEVICE_IGNORE}="1"

These lines will prevent ModemManager in Ubuntu from trying to take control of this device at boot up before the udev helper gobi_loader gets a change to load the firmware.   Now if all is going well reboot the machine and then check the following in a terminal;

#$ lsusb
Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 05c8:0403 Cheng Uei Precision Industry Co., Ltd Webcam
Bus 001 Device 003: ID 03f0:251d Hewlett-Packard Gobi 2000 Wireless Modem
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

You should notice that the product ID has changed from 241d to 251d, meaning that firmware is now loaded in the 3G modem.  I tried not rebooting this machine which turned out to be a mistake.  ModemManager is a pernickety piece of software that won’t do anything unless everything is 100% right.  I wasted a number of hours chasing my tail trying to get services shutdown and restarting stuff.

You should also see that there are now three tty USB devices attached to the system;

#$ ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2

If you don’t see these three devices then there is something wrong.  I’d suggest you start with dmesg and searching your way through syslog to find out why what’s gone wrong.  It can take a while.  When you do get things right about 13-15 seconds after the kernel loads you should see the firmware loaded into the modem and the additional USB serial ports being created.   If the firmware doesn’t load you will find error messages in syslog.

Now you should be able to configure the NetworkManager to actually use the Modem.  I simply went into NetworkManager -> Edit Connections and created a mobile broadband connection from scratch.   The APN we want to use for Telstra is “telstra.internet” and the rest is pretty much a vanilla install.

Once you’ve got the connection, done you should be able to connect to the internet via the cellular modem.

Oh and don’t forget to plug your SIM into the slot in the battery case.   Now you can sit back and enjoy Cellular Mobile data without any external USB dongle to snap off, or get left behind.

Yay !