Mer/Documentation/N810 GPS

Contents

Notes

  • These directions are confirmed to work on Mer 0.12.
  • All commands should be run as root.
  • All instances of "YOURUSERNAME" should be changed to whatever your user is named. Commands involving "YOURUSERNAME" [i]probably[/i] don't have to be run if your user is named "user", though this is unconfirmed.
  • The time to first fix (TTFF) is quite long (~30 min), and GPSD quits after the last client disconnects. Keep this in mind.

Directions

Step 1: Install the necessary files

Install the following packages from the Maemo Updates repository (you can install them on Maemo, then copy the packages from the apt cache):

libsupld1
osso-gpsd
libgpsmgr
libgpsbt (?)
gpsdriver

Step 2: Tweak /etc/init.d/libgpsbt

Edit /etc/init.d/libgpsbt and change all instances of "user:users" to "YOURUSERNAME:users" There should be 2 instances you need to change.

Step 3: Change ownership

Run:

chown -R YOURUSERNAME:users /var/lib/gps

Step 4: Make the necessary files

Make the following files:

/etc/default/gps5300driver.conf:

# /etc/default/gps5300driver.conf

# The user who can control the driver
GPS5300_USER=root

# Whether the driver will self-initialize, may or may not work (more on the may not side)
GPS5300_SELFINIT=true


/etc/init.d/gps5300driver:

#!/bin/bash

GPS5300_DRIVER='/usr/sbin/gps5300driver'
GPS5300_PIDFILE='/var/run/gps5300driver.pid'
GPS5300_PRELOAD='/usr/lib/libgps5300faker.so'
CONF=/etc/default/gps5300driver.conf

if [ -f $CONF ]; then
         . $CONF
fi

case $1 in
	start)
		echo "Starting GPS5300 driver"
		if ! [ -e /sys/devices/platform/gpio-switch/gps_reset/state ]; then
			echo "gps_reset state gpio switch missing"
#			return 1
		fi
			
		[ -z "${GPS5300_SELFINIT}" ] && GPS5300_SELFINIT=true
		${GPS5300_SELFINIT} || unset GPS5300_SELFINIT
		export GPS5300_SELFINIT
		
		[ -z "${GPS5300_USER}" ] && GPS5300_USER=root
		export GPS5300_USER
		
		export LD_PRELOAD=${GPS5300_PRELOAD}		
	
		start-stop-daemon --start \
			--quiet \
			--background \
			--pidfile "${GPS5300_PIDFILE}" \
			--make-pidfile \
			--exec "${GPS5300_DRIVER}"
#			--env "LD_PRELOAD=${GPS5300_PRELOAD}" \
#			--exec "${GPS5300_DRIVER}"
#		return 0
	;;

	stop)
		echo "Stopping GPS5300 driver"
		start-stop-daemon --stop \
			--quiet \
			--pidfile "${GPS5300_PIDFILE}"
		rm ${GPS5300_PIDFILE}
#		return 0
	;;

	restart|force-reload)
		$0 stop
		$0 start
	;;

	*)
		echo "Usage: $0: {start|stop|restart|force-reload}"
		exit 1
	;;
esac

Step 5: Copy gpsdriver

Make a copy of gpsdriver to prevent confusion

cp /usr/sbin/gpsdriver /usr/sbin/gps5300driver

Step 6: Install libgps5300faker.so

First of all, install the necessary packages (they may be removed later, this may be an excessive list or an incomplete list. Basically keep installing stuff until it stops complaining):

apt-get install build-essential m4 automake autoconf

Make the following files somewhere (they may be removed later):

preload_init.c

/*
 * Copyright 2009 Luke Dashjr <luke_n8x0_gps5300driver@dashjr.org>
 * Licensed for redistribution as-is;
 * contact me if you want something more permissive
 */

#define _GNU_SOURCE

#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

static struct sockaddr_un ctrl_sau = {
	AF_UNIX,
	"/var/lib/gps/gps_driver_ctrl\0",
};
#define CTRL_SCK_PATH ctrl_sau.sun_path

static int ctrl_sck = -1;

typedef int (*bind_t)(int, const struct sockaddr*, socklen_t);

int
bind(int sockfd, const struct sockaddr*addr, socklen_t addrlen) {
	static bind_t real = NULL;
	if (!real)
		real = dlsym(RTLD_NEXT, "bind");
	
	int rv = real(sockfd, addr, addrlen);
	
	if (
	    addr &&
	    addr->sa_family == AF_FILE &&
	    !strcmp(CTRL_SCK_PATH,
	            ((struct sockaddr_un*)addr)->sun_path
	           ) &&
	    getenv("GPS5300_SELFINIT") &&
	    1
	)
		ctrl_sck = sockfd;
	
	return rv;
}

typedef int (*listen_t)(int, int);

int
listen(int sockfd, int backlog) {
	static listen_t real = NULL;
	if (!real)
		real = dlsym(RTLD_NEXT, "listen");
	
	int rv = real(sockfd, backlog);
	
	if (sockfd == ctrl_sck && !fork())
	{
		// Child process :)
		
		int sck;
		char initcmd[] = "P 3\n";
		
		sck = socket(PF_FILE, SOCK_STREAM, 0);
		if (sck < 0)
			exit(1);
		if (connect(sck, &ctrl_sau, sizeof ctrl_sau))
			exit(1);
		write(sck, initcmd, sizeof initcmd);
		close(sck);
		
		exit(0);
	}
	
	return rv;
}

preload.c:

 /*
 * Copyright 2009 Luke Dashjr <luke_n8x0_gps5300driver@dashjr.org>
 * Licensed for redistribution as-is;
 * contact me if you want something more permissive
 */

#define _GNU_SOURCE

#include <dlfcn.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

typedef struct passwd* (*getpwnam_t)(const char*);

struct passwd *
getpwnam(const char *name) {
	static getpwnam_t real = NULL;
	if (!real)
		real = dlsym(RTLD_NEXT, "getpwnam");
	
	if (!strcmp(name, "user"))
	{
		const char*username = getenv("GPS5300_USER");
		if (username)
			name = username;
	}
	
	return real(name);
}

Compile them:

cd /path/to/source/files/
gcc -shared -fPIC -ldl preload.c preload_init.c -o libgps5300faker.so

Put libgps5300faker.so in /usr/lib (assuming you're still in the same directory):

cp libgps5300faker.so /usr/lib

Step 7: Reboot

Reboot:

reboot

Step 8: Prepare to use the GPS

Get ready to use the GPS:

/etc/init.d/libgpsbt restart
/etc/init.d/gpsdriver restart
/etc/init.d/gps5300driver restart

Step 9: Start GPSD

Start GPSD:

gpsd -n -N -D2 /dev/pgps

When you start getting messages like:

gpsd: <= GPS: $GPGGA,183757.000,4504.94573,N,09300.43367,W,1,04,2.7,288.8,M,-31.3,M,,*60
gpsd: <= GPS: $GPGLL,4504.94573,N,09300.43367,W,183757.000,A,A*42
gpsd: can't use GGA/GGL time until after ZDA or RMC has supplied a year.
gpsd: <= GPS: $GPGSA,A,3,31,11,30,32,,,,,,,,,5.9,2.7,5.3*3D
gpsd: <= GPS: $GPGST,183757.000,14.3,13.2,37.3,19.1,16.0,32.4,73.2*54

You have a lock and are ready to use your GPS (I've also gotten other messages indicating the GPS is ready. Basically anything new/other than what it routinely spits out should be a good indicator).