Oct 03,
2017

Hiding Emacs' Mouse Pointer

Greetings folks. Another afternoon spent shaving yaks.

Out of the box Emacs is configured to hide the mouse pointer when the keyboard is used, a sane default if you ask me, with only a small detail in its current implementation: the pointer is hidden only when is typed a self-inserting-character. In other words, moving the cursor with the keyboard doesn't hide the mouse pointer.

And in my case, the mouse pointer always lands where I want to read.

I've checked the available documentation and I can't find anything that can help me, so it seems that I need to hack the sources. So the other day I've tried to modify the move_point1 function in cmds.c with a tentative patch:

diff -u emacs-25.3/src/cmds.c emacs-25.3-mod/src/cmds.c
--- emacs-25.3/src/cmds.c
+++ emacs-25.3-mod/src/cmds.c
@@ -71,6 +71,8 @@
       xsignal0 (Qend_of_buffer);
     }

+  frame_make_pointer_invisible (SELECTED_FRAME ());
+
   SET_PT (new_point);
   return Qnil;
 }

Yay! It worked after the first attempt.

Well, it's not the cleanest solution as I've introduced at least one side effect: when used in combination with Gnome's windows sloppy focus mode2 the window focus event hide the pointer without touching the keyboard. For the moment it doesn't bother me and it's good enough, probably I need to put a condition to not hide the pointer if it's an X focus event.


  1. what other editors call cursor on Emacs is called point, in this post I've used the more used therm ↩︎

  2. I haven't tried with the other two modes ↩︎

 
 

Sep 22,
2017

SSH keys precedence

Greetings readers.

Summer is officially over, so I can finally bear to be in front of a computer monitor without the help of an AC unit, the thunderstorm of the last week lowered the temperatures to a human level so going outside for most of the day is pleasurable, if one can find a place not infested by mosquitoes.

Enough ramblings, today1 I've verified that the OpenSSH client doesn't try keys in alphabetical order when attempting public/private keys logins, but instead tries them according to their timestamp, starting with the oldest.

Good to know.

This reminds me a Gerald Sussman quote2:

Nowadays you muck around with incomprehensible or nonexistent man pages for software you don't know who wrote. You have to do basic science on your libraries to see how they work, trying out different inputs and seeing how the code reacts.

I should be honest, I haven't checked thoroughly the OpenSSH man pages, anyway those words resonated with me.


  1. memory doesn't help me, but I think I've already done this one some years ago during my day job ↩︎

  2. courtesy of Wingolog ↩︎

ssh
 
 

Aug 20,
2017

WiFi Woes Redux

Another glitch I found out after upgrading to Debian Stretch was that my desktop's wireless NIC has started using the Chinese regulatory domain instead of guessing the correct country code where I'm living or simply using the value that was specified in the WiFi settings. For the record, it's a TP-LINK TL-WN881ND based on the Atheros AR9287 chipset.

I'm not sure if it's a bug in the central regulatory domain agent daemon (CRDA) that is shipped with Debian or something broken in this card's firmware. I'm leaning on the latter as the notebook is working as expected and the chipsets aren't the same. Anyway, because of international regulations about radio interference, it seems I can't nonchalantly set the correct country code of my network card, in fact according to the documentation1:

"The kernel ignores regulatory domains sent to it if it does not expect them."

Yup, it works as advertised.

Trying to launch, for example COUNTRY=US crda from the command line, it fails and return -7 as exit code. By the way, is the same exit code that I've seen in the kernel logs2 where instead the crda is invoked from udev. In some ways the kernel isn't able to find which regulatory domain to set or doesn't agree with the value configured in /etc/default/crda and it applies the value stored in the card's EEPROM.

Now, I think there's a documented procedure to override a regulatory domain that I've found described in the kernel.org's Wiki; it consists of creating and installing local crypto keys to sign a modified regulatory domains DB and it looked quite convoluted and boring. To be honest I didn't read the entire wall of text.

As I will explain later, after peeking in the card's firmware I've found out that it's present the China ISO/IEC 3166 country code on it even if the card was destined for the European market3, so I asked myself if it wouldn't be easier to simply alter two nimble bytes with the desired country code and called it a day. In other words, wouldn't be faster to have a chance to brick the wireless NIC trying to fix an allegedly broken firmware, maybe using a third party unmaintained tool of unknown quality?

Interestingly enough, even if not exactly a case of the Betteridge's law of headlines, the answer in this case is yes, with only a small hitch that I eventually solved.

After scouring the web I indeed found an abandoned utility on code.google.com called iwleeprom that allegedly had the ability to flash the card's firmware and after briefly examining the available documentation, a single terse man page, it really looked of unknown quality as it mentioned only Intel wireless card models.

With iwleeprom I was able to dump the information stored in the card's EEPROM, like capabilities, channels, MAC address and what I was looking for, the regulatory domain. In this particular case it reported the value 0x809c. Ignoring the 0x8000 flag4, the value is 156 in decimal that corresponds to the China country code in the ISO/IEC 3166 list5.

Bingo!

Now it's only a matter of dumping the firmware, modifying it, calculating a new checksum, and writing it back on the card's EEPROM.

Regarding the small hitch I mentioned above, iwleeprom when dumping the firmware it calculates its checksum and reports the value stored on the card: the issue here is the two didn't matched. I suppose I can chalk this one as another thing that doesn't give confidence in the tool.

Undeterred I nonetheless tried to flash a modified firmware with the iwleeprom's calculated checksum and the obvious result was a soft brick. As I feared the wireless NIC refused to work with the applied changes.

Well, after looking at the kernel's ath9k sources, I managed to fix the checksum calculation; fortunately the change was trivial. The patch consists in commenting a single line in the iwleeprom's ath9k_eeprom_crc_calc function:

static bool ath9k_eeprom_crc_calc(struct pcidev *dev, uint16_t *crcp)
{
    uint16_t crc = 0, data;
    int i;

    if (!short_eeprom_size)
        return false;
    printf("Calculating EEPROM CRC");

    for (i=0; i<short_eeprom_size; i+=2) {
        if (2 == i) continue;
        if (!dev->ops->eeprom_read16(dev, short_eeprom_base + i, &data)) {
            printf(" !ERROR!\n");
            return false;
        }
        crc ^= data;
        if (!(i & 0xFFC0)) printf(".");
    }
    //crc ^= 0xFFFF; <-- The offending line
    if (crcp)
        *crcp = crc;
    printf("\n");
    return true;
}

The final exclusive OR with the 0xffff constant isn't required for this chipset.

For the modification part the interesting bits, pun intended, start at location 0x0102 with two bytes for the checksum in little-endian format (in this case 0x9187) followed by the two bytes of the country code at 0x0108 (in this case 0x809c) again in little-endian format:

00000100  d7 02 87 91 04 e0 16 00  9c 80 1f 00 07 00 13 37
00000110  d0 0d 03 03 00 00 00 00  00 00 00 1b 09 00 05 01
00000120  fb fa fa 00 00 00 00 00  00 00 00 00 00 00 00 00
00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

So after fixing the checksum calculation the plan is:

  1. dumping the firmware with sudo ./iwleeprom -d 0000:03:00.0 -o /tmp/ar9287.bin passing the correct PCI slot address with the -d option

  2. modifying the country code

  3. launching ./iwleeprom -n -i /tmp/ar9287-mod.bin -s to calculate a new checksum passing the -n option to operate only on files

  4. updating the checksum

  5. flashing the modified firmware to the card's EEPROM with sudo ./iwleeprom -d 0000:03:00.0 -i /tmp/ar9287.bin

  6. ...

  7. profit

Yay, success!

I can assure the concerned reader that no wireless NIC was harmed performing the above procedure, in fact the mentioned card is now happily connected with my access point using the expected country regulatory domain.

As a final note, I'm not encouraging the reader to tinker with his WiFi hardware, this is merely a reference to be used by my future self. Messing with radio stuff is serious business, especially with interference, fines aren't a remote possibility.


  1. quoting from the crda(8) man page ↩︎

  2. in the kernel logs the exit code is 249, the decimal value of -7 in two's complement ↩︎

  3. in my opinion they should have put a generic "world" regulatory domain instead of a specific country code ↩︎

  4. according to the Atheros documentation it's the COUNTRY_ERD_FLAG ↩︎

  5. the inquisitive reader can find the complete list on the Wikipedia page ↩︎