Installing Windows 10 on a Panasonic Toughbook CF-F9

In general the installation of Windows 10 on Toughbook CF-F8 or CF-F9 is unremarkable; either an upgrade or a fresh install on an empty drive will work. Then install Windows 7 64-bit drivers in a logical order (OS INF, common components, misc driver, other drivers, then the utilities). You can use the driver download manager to download them all beforehand.

There are only a couple of issues, specifically one serious one and one minor one.

The first (serious) issue is about the Intel Dynamic Power Management (ETM) driver, which is blacklisted in Windows 10, saying something along the lines that the driver is broken in Windows 10. First of all that’s a lie – the driver is working perfectly under Windows 10, and secondly, when this driver is absent, the Toughbook is unable to wake up from sleep (the CPU resets during wake-up), and the manual fan control (low/medium/high) isn’t working. This has been an issue in older versions of Windows and is still an issue in Windows 10. Needless to say, it’s a problem for a laptop to be unable to sleep.

So how do we install a blacklisted driver? The blacklisting is done at MSI level, so we need to install it manually:

  • Uninstall the built-in Intel Dynamic Power Management device, including the driver (can be found in Device Manager under the System category)
  • Go to DynamicPowerPerfMgmtDriver, right-click on Drivers\Etm.inf, select Install…
  • Copy x64\EtmDevPch.sys to \Windows\System32\Drivers
  • Download and import this reg file: install-etm.reg
  • Now go to the Video driver, right-click on IIPS\lmpcd.inf, select Install…
  • Reboot

Now to the second, minor issue (although I found it quite annoying). The Panasonic touchpad/wheelpad utility (the one that handles circular scrolling) isn’t working in Windows 10 metro apps (Edge browser, Store, etc.). To fix, download and install this patch, which basically is a shim that patches the utility to call SendInput instead of posting WM_MOUSEWHEEL messages.

All done! Enjoy!


BMW MRSZ “1 internal ECU error” fix

I lost almost an entire day trying to figure out what went wrong when I was playing with my E36 airbag module coding in an attempt to disable passenger seat occupancy detection.

I didn’t understand why most MRSZ settings were duplicated, such as these two:


I set only one of these to “nicht_aktiv”, after which the module threw an “internal ECU error” and the FS_LOESCHEN command returned ERROR_ECU_REJECTED. Even after I restored all coding settings back to their original values, the error remained.

As it turns out, after digging through 24KB of microcode, the reason to duplicate every setting is very simple – it is a form of EEPROM error detection. The unit periodically checks to see if every setting has the same value in both copies, and when that is not the case, a static error 195 is logged. Every error code above 100 is mapped to the “internal ECU error”, and when that happens the erase function is also blocked.

Fortunately, at the same time I also found a “secret” command to write EEPROM bytes. Not all areas can be written with that command, but at least the area where the errors are stored is writable.

Attached is an EDIABAS script that attempts to “reanimate” an MRSZ unit. Note that you need to restore the coding to a working state before running the script. NCSExpert’s SG_CODIEREN command will end with an error, that is because it tries to erase errors at the end of the process, which fails, the actual coding should in fact be OK.


Note – the script supports only MRSZ units (MRS v06, P/N 8374799), it does not support MRSZ2 (MRS v07, P/N 8372521), MRSZ3 or MRSZ4. The “secret” command simply does not exist in these modules. I do not know if it supports the older ZAE2 (P/N 8374798) units.

The source code of my MRSZ2 attempt can be found here. It includes working support for MRSZ.


Groovy is COOL

Of course Groovy is much more than Java, but for Java coders like myself, it can be seen as Java without its time-eating annoyances, the absolute top 3 of which, in my opinion, are:

1. Getters and setters are implicit

2. Lists, Maps and Regex are part of the syntax

3. Configuration is greatly simplified

Item 1 is self explanatory, I hope :) For the remaining two, here are some examples:

Working with collections:

def list = [5, 6, 7, 8]
for (i in list) println i
def map = [name:"Gromit", likes:"cheese", id:1234]
for (i in map) println "map[${i.key}] is ${i.value}"

Pulling Maven dependencies inline with your code, without any other configuration anywhere:

@Grab(group='mysql', module='mysql-connector-java', version='5.1.18')
driver = new com.mysql.jdbc.Driver()
Properties p = new Properties()
conn = driver.connect('jdbc:mysql://localhost/groovy-test', p)
st = conn.createStatement()
for (i in 1..10) {
 st.executeUpdate("insert into test(name,value,version) values('name${i}','value for name${i}',0)")

Of course Groovy is a dynamically typed language, and as such has its downsides. Since the compiler can’t type-check assignments, you get much more run-time errors like:

No signature of method: java.util.ArrayList.get() is applicable for argument types: (java.lang.String)


Cannot cast object ‘x’ with class ‘java.lang.String’ to class ‘int’

Most of these errors are caught when you try out your code for the first time, though, and are easily fixable. It’s just a bit annoying at the beginning for someone used to getting these at compile time rather than at run time.

To me, Groovy is still a clear winner if you want to boost your coding productivity🙂

Oh yeah, and the performance of Groovy is not significantly worse than that of Java (if you don’t use too many dynamic features), as I confirmed in this post.


Motorola AP-7131 dependent mode?

It seems that not all AP-7131’s are the same. There are some that are meant to be used only together with a central controller like RFS4000 or RFS6000.

This is called, in Motorola terms, ‘dependent mode’, and is hard-coded into the device. The “D” in the model ID stands for “dependent”, like in this example:

Motorola AP-7131-66000-D-WR

Such a device will not enable any radio unless directed to do so by a central controller.

One of the reasons this is done is to prevent theft of access points from public locations.


Detect MIME type of most popular Internet files

This code can detect among others PDF, Microsoft Word, Excel, Powerpoint & Visio, without even knowing the file extension.


sub detectMime(\$)
  my ($s)=@_;
  return 'text/html' if $$s =~ /^(\xEF\xBB\xBF)*\s*<(\!--|\!?doctype|html|head|body|title|h1)/is;
  return 'text/xml' if $$s =~ /^(\xEF\xBB\xBF)*\s*<\?xml/s;
  return 'application/rtf' if $$s =~ /^\{\\rtf/s;
  my @b=unpack('C520',$$s);
  return 'image/jpeg' if $b[0]==0xFF && $b[1]==0xD8;
  return 'image/gif' if $b[0]==0x47 && $b[1]==0x49 && $b[2]==0x46;
  return 'image/png' if $b[0]==0x89 && $b[1]==0x50 && $b[2]==0x4E && $b[3]==0x47;
  return 'image/bmp' if $b[0]==0x42 && $b[1]==0x4D;
  return 'image/tiff' if $b[0]==0x49 && $b[1]==0x49 && $b[2]==0x2A;
  return 'application/pdf' if $b[0]==0x25 && $b[1]==0x50 && $b[2]==0x44 && $b[3]==0x46;
  return 'image/x-icon' if $b[0]==0 && $b[1]==0 && $b[2]==1 && $b[3]==0 && $b[4]==1;
  if ($b[0]==0xD0 && $b[1]==0xCF && $b[2]==0x11 && $b[3]==0xE0 && @b>0x200) {
    return 'application/msword' if $b[0x200]==0xEC;
    return 'application/vnd.ms-excel' if $b[0x200]==0x09;
    return 'application/vnd.ms-powerpoint' if $b[0x200]==0x40;
    return 'application/vnd.visio' if $b[0x200]==0xFD;
  for (my $i=@b-1;$i>=0;$i--) { return 'application/octet-stream' if $b[$i]<32 && $b[$i]!=9 && $b[$i]!=10 && $b[$i]!=13 }
  return 'text/plain';

SDBM hash implementation in PHP

The SDBM hashing function is a simple and fast function that provides surprizingly uniform distributions of the hash value even when applied to a series of relatively short strings (3-7 characters). This makes it an excellent algorithm for organizing multiple files in sub-directories, for example, but the possible applications are, of course, endless.

Implementing the SDBM hashing in PHP is not an easy task, however. The SDBM hash function relies on a 32-bit overflow, which doesn’t work well in PHP due to its built-in overflow handling and automatic type conversion, which is also implemented differently on different platforms.

After much trial and error, the following cute piece of code has been found to perform correctly in PHP 5.2/5.3 on 32-bit as well as 64-bit systems.

function sdbmHash($str)
	$hash = 0; $n=strlen($str);
	for ($i=0; $i<$n; $i++) {
		$h1 = $hash << 6;
		if ($h1<0) $h1+=0x100000000;
		$h2 = $hash << 16;
		if ($h2<0) $h2+=0x100000000;
		$hash = (int)((int)ord($str[$i]) + $h1 + $h2 + $h3);
		if($hash<0) $hash=$hash+0x100000000;
	return $hash;

“MySQL server has gone away”

When you try to insert a BLOB that exceeds your server’s maximum packet size, even on a local server you will see “MySQL server has gone away” on the client side, and “Error 1153 Got a packet bigger than ‘max_allowed_packet’ bytes” in the server log. To fix this you need to decide what is the size of the largest BLOB you’ll ever insert, and set max_allowed_packet in my.ini accordingly, for example:

 max_allowed_packet = 200M