GPS / GIS Linux

TomTom One V3 buzzer output

I was just attempting to use the /dev/buz device on a TomTom One V3 for debugging purposes but the test code below failed on the attempt to open the device driver despite trying a few combinations of open flags. The device seemed to be installed OK but I noticed in the Barcelona kernel source it is written for exclusive access so presumably the main ttn application opens it. I need the navigator application open while debugging my app so tomorrow will take a look at getting something out of a serial port.

int fd = open("/dev/buz", O_RDONLY | O_NONBLOCK | O_NOCTTY); 
cout << "fd: " << fd << endl; 
int result = ioctl(_IO('U', 3), 0); 
cout << "result: " << result << endl; 
GPS / GIS Hardware

UBlox UTC Time

I’ve just discovered a time sync error with one of my embedded GPS systems that is part of a wireless system for performance monitoring of sporting events. One of the devices that sends a UTC timestamp to establish the start of an event was sending a time that appeared to be over 10 seconds out of sync with the GPS transmitters attached to participants in the event. Further testing against a known time reference uncovered the exact time difference was 15 seconds in the future which is the current difference between UTC time and GPS time.

It appears the UBlox LEA-4H and LEA-4S GPS receivers send out GPS time in their NMEA sentences until they have received a valid almanac and this is the first occasion when the GPS transmitters didn’t have time before the start of the event to receive an almanac. The UBlox receivers only appear to have the necessary data output to discriminate between GPS and UTC time in the versions of their firmware loaded into GPS modules specifically targetted at timing applications. The embedded host computer that receives data from the wireless network has an Internet connection so the solution in this case will be to sync the embedded PC clock to an Internet time source so that future times received can be treated as GPS time. Maximum wireless network latency is guaranteed to be less than 10 seconds so this should be a reliable solution.

Hardware Linux

Linux FriendyARM board

Recently I picked up a FriendARM board from E-Bay for $US110 which wasn’t a bad price for the package that included accessory cables and a parallel port JTAG dongle. Package also included Protel schematics for the board which is based on a Samsung S3C2440 ARM9 CPU and includes ethernet, serial, small EEPROM, LCD touch screen, audio in/out and a few other goodies including convenient access to some TTL general purpose I/O lines. The CDROM also included a few software packages it probably shouldn’t have ;-). Unfortunately a lot of the documentation is written in Chinese however I won’t have much trouble piecing things together from the schematic, kernel sources and example code that are largely in English.

I’d hoped to get some design ideas from the board and use the S3C2440 in an upcoming Linux industrial computer that I’m contemplating putting together. Unfortunately it appears Samsung are one of those companies that treats their datasheets like crown jewels and my request for a datasheet was declined. I probably could have persisted and obtained the datasheets but would like to keep the design open and don’t want end-users of the product to have to jump through hoops to optain the datasheets. At this stage I might tend towards an Atmel device like the AT91SAM9260 which is widely available and has datasheets and code examples that can be readily downloaded as you’d expect. It is also available in a PQFP package to avoid BGA setup costs.


VAX/VMS MACRO password checker

The following is come code I found I wrote many years ago in Digital VAX MACRO to check passwords for a particular username against a dictionary of words concatenated with a number.

.title    check_password


.psect    rw_data rd,wrt,noexe,noshr,long

pwdlist_fab:    $fab    fnm = <sys$library:VMS$PASSWORD_DICTIONARY.DATA>

pwdlist_rab:    $rab    fab = pwdlist_fab,-
rop = rah,-
ubf = rec_buff,-
usz = rec_size

rec_size = 32
rec_desc:    .word    rec_size
.word    0
.address rec_buff
rec_buff:    .blkb    rec_size

cur_count:    .long
max_count = 99
num_size = 2
cur_no:        .ascid    \99\

cur_pwd:    .word   rec_size+num_size
.word    0
.address 10$
10$:        .blkb    rec_size+num_size

cur_hash:    .blkb    8

username_len:    .word    12
.word    0
.address 10$
10$:        .blkb    12

pwd_list:    .word    1
.word    uai$_encrypt
.address encrypt
.address encrypt_len
.word    8
.word    uai$_pwd
.address pwd
.address pwd_len
.word    2
.word    uai$_salt
.address salt
.address salt_len
.word    0
.word    0
encrypt:    .byte
encrypt_len:    .word
pwd:        .blkb    8
pwd_len:    .word
salt:        .word
salt_len:    .word

usage_msg:    .ascid \VMS username must be specificed as a parameter\

.psect    code rd,nowrt,exe,shr,long

.entry    check_password,^m<>

; get username passed on command line - display error if not present

pushaq    username
calls    #1,g^lib$get_foreign
blbc    r0,error_exit
pushaw    username_len
pushaq    username
pushaq    username
calls    #3,g^str$trim
blbc    r0,error_exit
tstw    username_len
bnequ    get_pwd
pushaq    usage_msg
calls    #1,g^lib$put_output
brb    normal_exit

; retrieve the hashed password from the UAF file

get_pwd:    $getuai_s usrnam=username,-
blbc    r0,error_exit

; open the VMS password dictionary

open_dic:    $open    fab=pwdlist_fab
blbc    r0,error_exit
$connect rab=pwdlist_rab
blbc    r0,error_exit

; retrieve a word from the dictionary

word_loop:    $get    rab=pwdlist_rab
blbs    r0,remove_nulls
cmpl    r0,#rms$_eof
beql    normal_exit
brb    error_exit

; get rid of nulls on the end of the record and convert to uppercase

remove_nulls:    clrw    r1
movaq    rec_buff,r2
10$:        tstb    (r2)
beql    20$
incw    r1
incl    r2
brb    10$
20$:        movw    r1,rec_desc
pushaq    rec_desc
pushaq    rec_desc
calls    #2,g^str$upcase

; start back at zero for new word

clrl    cur_count

; append a number to the word

append_no:    pushl    #2
pushl    #1
pushaq    cur_no
pushal    cur_count
calls    #4,g^ots$cvt_l_tu

movw    #rec_size+num_size,cur_pwd
pushaq    cur_no
pushaq    rec_desc
pushaq    cur_pwd
calls    #3,g^str$concat
blbc    r0,error_exit

pushaw    cur_pwd
pushaq    cur_pwd
pushaq    cur_pwd
calls    #3,g^str$trim

; now we have all the info to hash a password

$hash_password_s -
blbc    r0,error_exit

; check if we have a match on the hashed password - if so display

cmpl    cur_hash,pwd
bneq    no_match
cmpl    cur_hash+4,pwd+4
bneq    no_match
pushaq    cur_pwd
calls    #1,g^lib$put_output
brb    normal_exit

; loop back 'max_count' times

no_match:    aoblss    #max_count,cur_count,append_no

; loop back for another word

brb    word_loop

normal_exit:    movl    #1,r0
error_exit:    ret

.end    check_password
Operating systems

Vista network changes for older devices

Recently I installed Vista x64 and had some hassles with some older gear caused by changes to the default behaviour of the TCP stack. An HP Colour LaserJet 4550N would occasionally print a page of junk, I had a few problems with a Cisco 827 ADSL router corrupting some packets and also had file corruption problems using wireless networking to an XP Toshiba laptop running over a WLAN.

The following were the things I did to turn off the new features which solved my problems. I started by turning off SMB2 by inserting the following registry entry:


Under device manager I disabled the following features for my network adapter:

IPv4 checksum offload
TCP Checksum Offload (IPv4)
UDP Checksum Offload (IPv4)

From an elevated command prompt ran the following to turn off TCP auto-tuning features:

netsh interface tcp set global autotuninglevel=disabled
netsh interface tcp set global rss=disabled

Then I typed ‘OptionalFeatures’ in the Windows start search box and turned off ‘Remote Differential Compression’

Linux Programming

Linux kill process code fragment

Small C++ source code fragment to kill a certain number of instances of a process running under Linux. For example the following sends a terminate signal to the first 999 processes with the process name Tomahawk.

killproc(“Tomahawk”, “-TERM”, 999);

int killproc(const string procname, const string killcmd, const int killcnt)
	int proccnt = 0;
	const string procdir("/proc");

	DIR* dir = opendir(procdir.c_str());
	if (!dir)
		return 0;
	string searchstr = "(" + procname + ")";
	struct dirent *d;
	while ((d = readdir(dir)) &amp;&amp; proccnt &lt; killcnt)
		string dirname(d-&amp;gt;d_name);
		if( d-&gt;d_type == DT_DIR &amp;&amp; dirname != "." &amp;amp;&amp;amp; dirname != ".." &amp;amp;&amp;amp; isdigit(dirname[0]))
			string fn = procdir + "/" + dirname + "/stat";
			ifstream f(fn.c_str());
			if (f.is_open())
				string line;
			    if (getline (f, line) &amp;&amp; line.find(searchstr) != string::npos)
			    	string procid = line.substr(0, line.find(" "));
					string cmd = "kill " + killcmd + " " + procid;
	return proccnt;