Marc's Public Blog - Linux Hacking


All | Aquariums | Arduino | Btrfs | Cars | Cats | Clubbing | Dining | Diving | Electronics | Exercising | Flying | Hiking | Linux | Linuxha | Museums | Public | Rc | Sciencemuseums | Snow | Solar | Trips

This page has a few of my blog entries about linux, but my main linux page is here
Picture of Linus


Table of Content for linux:

More pages: March 2018 January 2018 September 2017 January 2017 October 2016 August 2016 July 2016 June 2016 February 2016 January 2016 May 2015 March 2015 January 2015 October 2014 May 2014 April 2014 March 2014 January 2014 November 2013 September 2013 May 2013 March 2013 January 2013 December 2012 August 2012 May 2012 March 2012 January 2012 December 2011 August 2011 July 2011 January 2011 October 2010 August 2010 June 2010 April 2010 March 2010 January 2010 December 2009 November 2009 September 2009 August 2009 July 2009 May 2009 January 2009 December 2008 November 2008 October 2008 January 2008 November 2007 August 2007 July 2006 January 2006 August 2005 April 2005 November 2004 March 2004 February 2004




2018/03/09 Btrfs Tips: Rescuing A Btrfs Send Receive Relationship
π 2018-03-09 01:01 in Btrfs, Linux
I had a problem when migrating disks and moving read only btrfs receive snapshots. I did a
btrfs snapshot dir1/Video_ro.20180220_21:03:41 dir2/Video_ro.20180220_21:03:41 
which in turn broke the snapshot by making it read-write and losing the btrfs receive relationship (Received UUID)

Later, I wanted to re-establish the btrfs send/receive relationship since it was an 8TB subvolume, and I wanted to avoid having to copy back all the data I already had there. Simply making the destination snapshot read only again did not work

The solution was python-btrfs, and this code: https://github.com/knorrie/python-btrfs/commit/1ace623f95300ecf581b1182780fd6432a46b24d

gargamel:python-btrfs/examples# ./set_received_uuid.py 2afc7a5e-107f-d54b-8929-197b80b70828 31337 1234.5678 /mnt/btrfs_bigbackup/DS1/Video_ro.20180220_21:03:411G Current subvolume information: subvol_id: 94887 received_uuid: 00000000-0000-0000-0000-000000000000 stime: 0.0 (1970-01-01T00:00:00) stransid: 0 rtime: 0.0 (1970-01-01T00:00:00) rtransid: 0

Setting received subvolume...

Resulting subvolume information: subvol_id: 94887 received_uuid: 2afc7a5e-107f-d54b-8929-197b80b70828 stime: 1234.5678 (1970-01-01T00:20:34.567800) stransid: 31337 rtime: 1520488877.415709329 (2018-03-08T06:01:17.415709) rtransid: 255755

Then make it read-only again: gargamel:python-btrfs/examples# btrfs property set -ts /mnt/btrfs_bigbackup/DS1/Video_ro.20180220_21:03:41 ro true

But this didn't work: ABORT: btrfs send -p /mnt/btrfs_pool1/Video_ro.20180220_21:03:41 Video_ro.20180308_07:50:06 | btrfs receive /mnt/btrfs_bigbackup/DS1//. failed At subvol Video_ro.20180308_07:50:06 At snapshot Video_ro.20180308_07:50:06 ERROR: cannot find parent subvolume

You can see that with set_received_uuid.py, I set Received UUID to match UUID on the source:

gargamel:/mnt/btrfs_pool1# btrfs subvolume show /mnt/btrfs_bigbackup/DS1/Video_ro.20180220_21:03:41 DS1/Video_ro.20180220_21:03:41
        Name:                   Video_ro.20180220_21:03:41
        UUID:                   cb4f343c-5e79-7f49-adf0-7ce0b29f23b3
        Parent UUID:            0e220a4f-6426-4745-8399-0da0084f8b23 
        Received UUID:          2afc7a5e-107f-d54b-8929-197b80b70828 << changed this
        Creation time:          2018-02-20 21:13:36 -0800
        Subvolume ID:           94887
        Generation:             250689
        Gen at creation:        250689
        Parent ID:              89160
        Top level ID:           89160
        Flags:                  readonly
        Snapshot(s):

Name: Video_ro.20180220_21:03:41 UUID: 2afc7a5e-107f-d54b-8929-197b80b70828 Parent UUID: e5ec5c1e-6b49-084e-8820-5a8cfaa1b089 Received UUID: 0e220a4f-6426-4745-8399-0da0084f8b23 Creation time: 2018-02-20 21:03:42 -0800 Subvolume ID: 11228 Generation: 4174 Gen at creation: 4150 Parent ID: 5 Top level ID: 5 Flags: readonly

Turns out however that because the source had a Parent UUID value too, I was actually supposed to set Received UUID on the destination to it:

gargamel:python-btrfs/examples# ./set_received_uuid.py 0e220a4f-6426-4745-8399-0da0084f8b23 313 37 1234.5678 /mnt/btrfs_bigbackup/DS1/Video_ro.20180220_21:03:41 Current subvolume information: subvol_id: 94887 received_uuid: 2afc7a5e-107f-d54b-8929-197b80b70828 stime: 1234.5678 (1970-01-01T00:20:34.567800) stransid: 31337 rtime: 1520488877.415709329 (2018-03-08T06:01:17.415709) rtransid: 255755

Setting received subvolume...

Resulting subvolume information: subvol_id: 94887 received_uuid: 0e220a4f-6426-4745-8399-0da0084f8b23 stime: 1234.5678 (1970-01-01T00:20:34.567800) stransid: 31337 rtime: 1520537034.890253770 (2018-03-08T19:23:54.890254) rtransid: 256119

gargamel:python-btrfs/examples# btrfs property set -ts /mnt/btrfs_bigbackup/DS1/Video_ro.201802 20_21:03:41 ro true

After this, I was able to re-start my btrfs send/receive and /mnt/btrfs_bigbackup/DS1/Video_ro.201802 20_21:03:41 was properly accepted as a destination. Yeah!

2018/01/22 Lolibot, FPGA Primer, MicroPython for ESP8266/ESP32 and Protocol Analysis at Open Hardware Miniconf at Linux.Conf.au 2018
π 2018-01-22 01:01 in Arduino, Linux
Got to play with a lot of hardware at LCA 2018:
  • ESP32 micropython programmed robot
  • Learned the very basics (and pains) of how to program an FPGA
  • MicroPython programming and handling
  • Protocol Analysis (1wire) with a USB protocol sniffer.
  • Definitely worth the time I spent, even if some miniconfs made me miss a bunch of talks, but it was worth it :)

    Lolibot:







    our fearless team was honest about how they do the work every year :)
    our fearless team was honest about how they do the work every year :)

    The next day, I went to the FPGA training/miniconf:


    Bunnie Huang was one of the attendees
    Bunnie Huang was one of the attendees

    FPGAs are definitely 'interesting', you can use some of the gates to emulate a CPU, and others to run bare metal code
    FPGAs are definitely 'interesting', you can use some of the gates to emulate a CPU, and others to run bare metal code

    It was useful to learn more about MicroPython the next day, definitely a faster way to work on ESP8266/ESP32 SOCs:


    ESP32
    ESP32


    Tim nicely setup a hardware rig to flash the little TOMU boards that fit in your USB slot:


    The last day, we learned how to use a USB logic analyser to debug 1wire timing issues:


    protocol analysis is what Tridge eats for breakfast ;)
    protocol analysis is what Tridge eats for breakfast ;)

    2018/01/22 Linux.Conf.au 2018 in Sydney
    π 2018-01-22 01:01 in Linux
    Another year, another LCA still. Back to Sydney for the 3rd time. Outside of the nice talks, and the fantastic work of recording all the talks and posting them almost real time, the highlight of LCA this year were [all the open hardware miniconfs I was able to attend|perso/arduino/post_2018-01-22_Lolibot_-FPGA-Primer_-MicroPython-for-ESP8266-ESP32-and-Protocol-Analysis-at-Open-Hardware-Miniconf-at-Linux_Conf_au-2018.html].

    A few pictures from the conf:

    Selfie!
    Selfie!



    I got to meet and chat with Bunnie Huang, cool
    I got to meet and chat with Bunnie Huang, cool

    Like every year, we had the penguin dinner and the PDNS:



    winner of the best suit!
    winner of the best suit!



    Random slides:







    looking forward to next year
    looking forward to next year

    See more images for Linux.Conf.au 2018 in Sydney
    2017/09/03 Xorg Switching From Xmodmap To Xkbcomp and Setxkbmap
    π 2017-09-03 01:01 in Linux
    I've been typing french on qwerty keyboards for close to 25 years. Using dead keys is a pain, and having characters like ` be dead key characters without using a compose key to enable them as dead characters, is even more of a pain.
    While the compose solution works, compose + ' + release + e to get é is kind of painful, so I wrote an xmodmap file that simply allowed right alt + e for é, right alt + shift + e for è.

    After 20+ years of using this xmodmap file with Xorg, it finally stopped working and causing more Xorg bugs that were not going to be fixed.

    keycode 105 = Multi_key
    keycode 108 = Mode_switch Alt_R Meta_R
    

    keycode 15 = 6 asciicircum dead_circumflex dead_circumflex keycode 49 = grave asciitilde dead_grave dead_grave keycode 48 = apostrophe quotedbl dead_acute dead_diaeresis

    keycode 38 = a A agrave agrave acircumflex adiaeresis keycode 26 = e E eacute egrave ecircumflex ediaeresis keycode 30 = u U ugrave ugrave ucircumflex udiaeresis keycode 31 = i I icircumflex idiaeresis keycode 32 = o O ocircumflex odiaeresis keycode 54 = c C ccedilla ccedilla

    I'll skip the choice words on the Xorg team for just letting xmodmap rot and die. Then, I'll express more dissatisfaction on how they didn't just give a converter. This "I'm going to break you and I don't really care" attitude, even if non willful, is not cool.

    So, I was left to fix my own problem, ok, after all I've been fixing linux problems for more than 20 years, so it can't be so bad, right? Well, it was. It took me hours and hours over multiple days. Searching implies that something seemingly simple as typing

    setxkbmap -model pc104 -layout us -variant intl (or altgr-intl)
    should work, but it did not. I got the compose key working on right CTRL, but not right ALT.

    More googling gave me this:

    setxkbmap -model pc104 -layout us -variant intl (or altgr-intl) -option -option lv3:ralt_switch,compose:rctrl,eurosign:4
    And finally I could get € by typing right ALT + 4, but I didn't get é when I typed right ALT + e. Dead keys did work though (right CTRL + ' + e = é), but that's a lot slower than just typing right ALT + e at the same time.

    After hours of going nowhere on reading that it should work, when it clearly didn't, I finally managed to dump my key mappings (that along isn't really documented well either):

    xkbcomp -xkb :0 
    actually dumps all the keys into a file called server-0.xkb. I then started editing it, and realized that my Xmodmap converted file had
        key <AD03> {
            type= "ALPHABETIC",
            symbols[Group1]= [               e,               E ]
            symbols[Group2]= [          eacute,          egrave ],
            symbols[Group3]= [     ecircumflex,      ediaeresis ],
            symbols[Group4]= [     ecircumflex,      ediaeresis ]
        };
    when apparently I needed:
        key <AD03> {
            type= "FOUR_LEVEL",
            symbols[Group1]= [               e,               E ,          eacute,          egrave ]
        };
    (lvl3 mapping doesn't seem to activate Group2 reliably, or at all, so I had to switch from type= "ALPHABETIC" to type= "FOUR_LEVEL" and that _finally_ worked).

    So now I have a ~/xkb-keymap file that I can load with

    xkbcomp ~/xkb-keymap :0
    Honestly, I have no idea why I had to do all this, or why it works apparently more simply for others. I have xorg 1:7.7+19 on debian testing.

    I'm attaching my whole file if it helps someone (congratulation if google brings you to this page)

    xkb_keymap {
    xkb_keycodes "evdev+aliases(qwerty)" {
        minimum = 8;
        maximum = 255;
         <ESC> = 9;
        <AE01> = 10;
        <AE02> = 11;
        <AE03> = 12;
        <AE04> = 13;
        <AE05> = 14;
        <AE06> = 15;
        <AE07> = 16;
        <AE08> = 17;
        <AE09> = 18;
        <AE10> = 19;
        <AE11> = 20;
        <AE12> = 21;
        <BKSP> = 22;
         <TAB> = 23;
        <AD01> = 24;
        <AD02> = 25;
        <AD03> = 26;
        <AD04> = 27;
        <AD05> = 28;
        <AD06> = 29;
        <AD07> = 30;
        <AD08> = 31;
        <AD09> = 32;
        <AD10> = 33;
        <AD11> = 34;
        <AD12> = 35;
        <RTRN> = 36;
        <LCTL> = 37;
        <AC01> = 38;
        <AC02> = 39;
        <AC03> = 40;
        <AC04> = 41;
        <AC05> = 42;
        <AC06> = 43;
        <AC07> = 44;
        <AC08> = 45;
        <AC09> = 46;
        <AC10> = 47;
        <AC11> = 48;
        <TLDE> = 49;
        <LFSH> = 50;
        <BKSL> = 51;
        <AB01> = 52;
        <AB02> = 53;
        <AB03> = 54;
        <AB04> = 55;
        <AB05> = 56;
        <AB06> = 57;
        <AB07> = 58;
        <AB08> = 59;
        <AB09> = 60;
        <AB10> = 61;
        <RTSH> = 62;
        <KPMU> = 63;
        <LALT> = 64;
        <SPCE> = 65;
        <CAPS> = 66;
        <FK01> = 67;
        <FK02> = 68;
        <FK03> = 69;
        <FK04> = 70;
        <FK05> = 71;
        <FK06> = 72;
        <FK07> = 73;
        <FK08> = 74;
        <FK09> = 75;
        <FK10> = 76;
        <NMLK> = 77;
        <SCLK> = 78;
         <KP7> = 79;
         <KP8> = 80;
         <KP9> = 81;
        <KPSU> = 82;
         <KP4> = 83;
         <KP5> = 84;
         <KP6> = 85;
        <KPAD> = 86;
         <KP1> = 87;
         <KP2> = 88;
         <KP3> = 89;
         <KP0> = 90;
        <KPDL> = 91;
        <LVL3> = 92;
        <LSGT> = 94;
        <FK11> = 95;
        <FK12> = 96;
        <KATA> = 98;
        <HIRA> = 99;
        <HENK> = 100;
        <HKTG> = 101;
        <MUHE> = 102;
        <KPEN> = 104;
        <RCTL> = 105;
        <KPDV> = 106;
        <PRSC> = 107;
        <RALT> = 108;
        <LNFD> = 109;
        <HOME> = 110;
          <UP> = 111;
        <PGUP> = 112;
        <LEFT> = 113;
        <RGHT> = 114;
         <END> = 115;
        <DOWN> = 116;
        <PGDN> = 117;
         <INS> = 118;
        <DELE> = 119;
        <MUTE> = 121;
        <VOL-> = 122;
        <VOL+> = 123;
        <POWR> = 124;
        <KPEQ> = 125;
        <I126> = 126;
        <PAUS> = 127;
        <I128> = 128;
        <I129> = 129;
        <HNGL> = 130;
        <HJCV> = 131;
        <LWIN> = 133;
        <RWIN> = 134;
        <COMP> = 135;
        <STOP> = 136;
        <AGAI> = 137;
        <PROP> = 138;
        <UNDO> = 139;
        <FRNT> = 140;
        <COPY> = 141;
        <OPEN> = 142;
        <PAST> = 143;
        <FIND> = 144;
         <CUT> = 145;
        <HELP> = 146;
        <I147> = 147;
        <I148> = 148;
        <I150> = 150;
        <I151> = 151;
        <I152> = 152;
        <I153> = 153;
        <I155> = 155;
        <I156> = 156;
        <I157> = 157;
        <I158> = 158;
        <I159> = 159;
        <I160> = 160;
        <I162> = 162;
        <I163> = 163;
        <I164> = 164;
        <I165> = 165;
        <I166> = 166;
        <I167> = 167;
        <I169> = 169;
        <I170> = 170;
        <I171> = 171;
        <I172> = 172;
        <I173> = 173;
        <I174> = 174;
        <I175> = 175;
        <I176> = 176;
        <I177> = 177;
        <I179> = 179;
        <I180> = 180;
        <I181> = 181;
        <I182> = 182;
        <I185> = 185;
        <I186> = 186;
        <I187> = 187;
        <I188> = 188;
        <I189> = 189;
        <I190> = 190;
        <FK13> = 191;
        <FK14> = 192;
        <FK15> = 193;
        <FK16> = 194;
        <FK17> = 195;
        <FK18> = 196;
        <FK21> = 199;
        <FK22> = 200;
        <FK23> = 201;
        <MDSW> = 203;
         <ALT> = 204;
        <META> = 205;
        <SUPR> = 206;
        <HYPR> = 207;
        <I208> = 208;
        <I209> = 209;
        <I210> = 210;
        <I211> = 211;
        <I212> = 212;
        <I213> = 213;
        <I214> = 214;
        <I215> = 215;
        <I216> = 216;
        <I218> = 218;
        <I220> = 220;
        <I223> = 223;
        <I224> = 224;
        <I225> = 225;
        <I226> = 226;
        <I227> = 227;
        <I228> = 228;
        <I229> = 229;
        <I231> = 231;
        <I232> = 232;
        <I233> = 233;
        <I234> = 234;
        <I235> = 235;
        <I236> = 236;
        <I237> = 237;
        <I238> = 238;
        <I239> = 239;
        <I240> = 240;
        <I241> = 241;
        <I242> = 242;
        <I243> = 243;
        <I244> = 244;
        <I245> = 245;
        <I246> = 246;
        indicator 1 = "Caps Lock";
        indicator 2 = "Num Lock";
        indicator 3 = "Scroll Lock";
        indicator 4 = "Compose";
        indicator 5 = "Kana";
        indicator 6 = "Sleep";
        indicator 7 = "Suspend";
        indicator 8 = "Mute";
        indicator 9 = "Misc";
        indicator 10 = "Mail";
        indicator 11 = "Charging";
        virtual indicator 12 = "Shift Lock";
        virtual indicator 13 = "Group 2";
        virtual indicator 14 = "Mouse Keys";
        alias <AC12> = <BKSL>;
        alias <MENU> = <COMP>;
        alias <HZTG> = <TLDE>;
        alias <LMTA> = <LWIN>;
        alias <RMTA> = <RWIN>;
        alias <ALGR> = <RALT>;
        alias <KPPT> = <I129>;
        alias <LatQ> = <AD01>;
        alias <LatW> = <AD02>;
        alias <LatE> = <AD03>;
        alias <LatR> = <AD04>;
        alias <LatT> = <AD05>;
        alias <LatY> = <AD06>;
        alias <LatU> = <AD07>;
        alias <LatI> = <AD08>;
        alias <LatO> = <AD09>;
        alias <LatP> = <AD10>;
        alias <LatA> = <AC01>;
        alias <LatS> = <AC02>;
        alias <LatD> = <AC03>;
        alias <LatF> = <AC04>;
        alias <LatG> = <AC05>;
        alias <LatH> = <AC06>;
        alias <LatJ> = <AC07>;
        alias <LatK> = <AC08>;
        alias <LatL> = <AC09>;
        alias <LatZ> = <AB01>;
        alias <LatX> = <AB02>;
        alias <LatC> = <AB03>;
        alias <LatV> = <AB04>;
        alias <LatB> = <AB05>;
        alias <LatN> = <AB06>;
        alias <LatM> = <AB07>;
    };
    

    xkb_types "complete" {

    virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;

    type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= Level2; map[NumLock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Control+Alt; map[Control+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift+Lock]= Level1; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Control]= Level5; map[Shift+Lock+Control]= Level5; map[Shift+Control]= Level6; map[Lock+Control]= Level6; map[Control+LevelThree]= Level7; map[Shift+Lock+Control+LevelThree]= Level7; map[Shift+Control+LevelThree]= Level8; map[Lock+Control+LevelThree]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; level_name[Level4]= "Shift Level3"; level_name[Level5]= "Ctrl"; level_name[Level6]= "Shift Ctrl"; level_name[Level7]= "Level3 Ctrl"; level_name[Level8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level8; map[Shift+Lock+LevelThree+LevelFive]= Level7; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= Level8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= Level1; preserve[Shift+Lock+LevelFive]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift+NumLock]= Level1; map[NumLock]= Level2; map[Shift]= Level2; map[LevelThree]= Level3; map[NumLock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= Level2; map[Shift+LevelThree]= Level3; map[Control+Alt]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Alt Base"; level_name[Level3]= "Shift Alt"; level_name[Level4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level4; preserve[Lock]= Lock; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "AltGr Base"; level_name[Level4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock]= Level5; map[Shift+Lock]= Level2; map[Lock+LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= Level2; map[NumLock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[NumLock+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Alt Number"; }; };

    xkb_compatibility "complete" {

    virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;

    interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= ISOLock(modifiers=modMapMods,affect=all); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay1); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay2); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86Ungrab+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x55,data[1]=0x6e,data[2]=0x67,data[3]=0x72,data[4]=0x61,data[5]=0x62,data[6]=0x00); }; interpret XF86ClearGrab+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x43,data[1]=0x6c,data[2]=0x73,data[3]=0x47,data[4]=0x72,data[5]=0x62,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { !allowExplicit; whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { !allowExplicit; whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { !allowExplicit; whichModState= locked; modifiers= Shift; }; indicator "Group 2" { !allowExplicit; groups= 0xfe; }; indicator "Mouse Keys" { indicatorDrivesKeyboard; controls= mouseKeys; }; };

    xkb_symbols "pc+us+inet(evdev)+level3(ralt_switch)+compose(rctrl)+eurosign(4)" {

    name[group1]="English (US)";

    key <ESC> { [ Escape ] }; key <AE01> { [ 1, exclam ] }; key <AE02> { [ 2, at ] }; key <AE03> { [ 3, numbersign ] }; key <AE04> { type= "FOUR_LEVEL", symbols[Group1]= [ 4, dollar, EuroSign, NoSymbol ] }; key <AE05> { [ 5, percent ] }; key <AE06> { [ 6, asciicircum ] }; key <AE07> { [ 7, ampersand ] }; key <AE08> { [ 8, asterisk ] }; key <AE09> { [ 9, parenleft ] }; key <AE10> { [ 0, parenright ] }; key <AE11> { [ minus, underscore ] }; key <AE12> { [ equal, plus ] }; key <BKSP> { [ BackSpace ] }; key <TAB> { [ Tab, ISO_Left_Tab ] }; key <AD01> { type= "ALPHABETIC", symbols[Group1]= [ q, Q ] }; key <AD02> { type= "ALPHABETIC", symbols[Group1]= [ w, W ] }; key <AD03> { type= "FOUR_LEVEL", symbols[Group1]= [ e, E , eacute, egrave ] }; key <AD04> { type= "ALPHABETIC", symbols[Group1]= [ r, R ] }; key <AD05> { type= "ALPHABETIC", symbols[Group1]= [ t, T ] }; key <AD06> { type= "ALPHABETIC", symbols[Group1]= [ y, Y ] }; key <AD07> { type= "FOUR_LEVEL", symbols[Group1]= [ u, U, ugrave, ucircumflex ] }; key <AD08> { type= "FOUR_LEVEL", symbols[Group1]= [ i, I, icircumflex, idiaeresis ] }; key <AD09> { type= "FOUR_LEVEL", symbols[Group1]= [ o, O, ocircumflex, odiaeresis ] }; key <AD10> { type= "ALPHABETIC", symbols[Group1]= [ p, P ] }; key <AD11> { [ bracketleft, braceleft ] }; key <AD12> { [ bracketright, braceright ] }; key <RTRN> { [ Return ] }; key <LCTL> { [ Control_L ] }; key <AC01> { type= "FOUR_LEVEL", symbols[Group1]= [ a, A, agrave, acircumflex ] }; key <AC02> { type= "ALPHABETIC", symbols[Group1]= [ s, S ] }; key <AC03> { type= "ALPHABETIC", symbols[Group1]= [ d, D ] }; key <AC04> { type= "ALPHABETIC", symbols[Group1]= [ f, F ] }; key <AC05> { type= "ALPHABETIC", symbols[Group1]= [ g, G ] }; key <AC06> { type= "ALPHABETIC", symbols[Group1]= [ h, H ] }; key <AC07> { type= "ALPHABETIC", symbols[Group1]= [ j, J ] }; key <AC08> { type= "ALPHABETIC", symbols[Group1]= [ k, K ] }; key <AC09> { type= "ALPHABETIC", symbols[Group1]= [ l, L ] }; key <AC10> { [ semicolon, colon ] }; key <AC11> { [ apostrophe, quotedbl ] }; key <TLDE> { [ grave, asciitilde ] }; key <LFSH> { [ Shift_L ] }; key <BKSL> { [ backslash, bar ] }; key <AB01> { type= "ALPHABETIC", symbols[Group1]= [ z, Z ] }; key <AB02> { type= "ALPHABETIC", symbols[Group1]= [ x, X ] }; key <AB03> { type= "FOUR_LEVEL", symbols[Group1]= [ c, C, ccedilla, ccedilla ] }; key <AB04> { type= "ALPHABETIC", symbols[Group1]= [ v, V ] }; key <AB05> { type= "ALPHABETIC", symbols[Group1]= [ b, B ] }; key <AB06> { type= "ALPHABETIC", symbols[Group1]= [ n, N ] }; key <AB07> { type= "ALPHABETIC", symbols[Group1]= [ m, M ] }; key <AB08> { [ comma, less ] }; key <AB09> { [ period, greater ] }; key <AB10> { [ slash, question ] }; key <RTSH> { [ Shift_R ] }; key <KPMU> { type= "CTRL+ALT", symbols[Group1]= [ KP_Multiply, XF86ClearGrab ] }; key <LALT> { [ Alt_L, Meta_L ] }; key <SPCE> { [ space ] }; key <CAPS> { [ Caps_Lock ] }; key <FK01> { type= "CTRL+ALT", symbols[Group1]= [ F1, XF86Switch_VT_1 ] }; key <FK02> { type= "CTRL+ALT", symbols[Group1]= [ F2, XF86Switch_VT_2 ] }; key <FK03> { type= "CTRL+ALT", symbols[Group1]= [ F3, XF86Switch_VT_3 ] }; key <FK04> { type= "CTRL+ALT", symbols[Group1]= [ F4, XF86Switch_VT_4 ] }; key <FK05> { type= "CTRL+ALT", symbols[Group1]= [ F5, XF86Switch_VT_5 ] }; key <FK06> { type= "CTRL+ALT", symbols[Group1]= [ F6, XF86Switch_VT_6 ] }; key <FK07> { type= "CTRL+ALT", symbols[Group1]= [ F7, XF86Switch_VT_7 ] }; key <FK08> { type= "CTRL+ALT", symbols[Group1]= [ F8, XF86Switch_VT_8 ] }; key <FK09> { type= "CTRL+ALT", symbols[Group1]= [ F9, XF86Switch_VT_9 ] }; key <FK10> { type= "CTRL+ALT", symbols[Group1]= [ F10, XF86Switch_VT_10 ] }; key <NMLK> { [ Num_Lock ] }; key <SCLK> { [ Scroll_Lock ] }; key <KP7> { [ KP_Home, KP_7 ] }; key <KP8> { [ KP_Up, KP_8 ] }; key <KP9> { [ KP_Prior, KP_9 ] }; key <KPSU> { type= "CTRL+ALT", symbols[Group1]= [ KP_Subtract, XF86Prev_VMode ] }; key <KP4> { [ KP_Left, KP_4 ] }; key <KP5> { [ KP_Begin, KP_5 ] }; key <KP6> { [ KP_Right, KP_6 ] }; key <KPAD> { type= "CTRL+ALT", symbols[Group1]= [ KP_Add, XF86Next_VMode ] }; key <KP1> { [ KP_End, KP_1 ] }; key <KP2> { [ KP_Down, KP_2 ] }; key <KP3> { [ KP_Next, KP_3 ] }; key <KP0> { [ KP_Insert, KP_0 ] }; key <KPDL> { [ KP_Delete, KP_Decimal ] }; key <LVL3> { [ ISO_Level3_Shift ] }; key <LSGT> { type= "FOUR_LEVEL", symbols[Group1]= [ less, greater, bar, brokenbar ] }; key <FK11> { type= "CTRL+ALT", symbols[Group1]= [ F11, XF86Switch_VT_11 ] }; key <FK12> { type= "CTRL+ALT", symbols[Group1]= [ F12, XF86Switch_VT_12 ] }; key <KATA> { [ Katakana ] }; key <HIRA> { [ Hiragana ] }; key <HENK> { [ Henkan_Mode ] }; key <HKTG> { [ Hiragana_Katakana ] }; key <MUHE> { [ Muhenkan ] }; key <KPEN> { [ KP_Enter ] }; key <RCTL> { type= "TWO_LEVEL", symbols[Group1]= [ Multi_key, Multi_key ] }; key <KPDV> { type= "CTRL+ALT", symbols[Group1]= [ KP_Divide, XF86Ungrab ] }; key <PRSC> { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key <RALT> { type= "ONE_LEVEL", symbols[Group1]= [ ISO_Level3_Shift ] }; key <LNFD> { [ Linefeed ] }; key <HOME> { [ Home ] }; key <UP> { [ Up ] }; key <PGUP> { [ Prior ] }; key <LEFT> { [ Left ] }; key <RGHT> { [ Right ] }; key <END> { [ End ] }; key <DOWN> { [ Down ] }; key <PGDN> { [ Next ] }; key <INS> { [ Insert ] }; key <DELE> { [ Delete ] }; key <MUTE> { [ XF86AudioMute ] }; key <VOL-> { [ XF86AudioLowerVolume ] }; key <VOL+> { [ XF86AudioRaiseVolume ] }; key <POWR> { [ XF86PowerOff ] }; key <KPEQ> { [ KP_Equal ] }; key <I126> { [ plusminus ] }; key <PAUS> { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; key <I128> { [ XF86LaunchA ] }; key <I129> { [ KP_Decimal, KP_Decimal ] }; key <HNGL> { [ Hangul ] }; key <HJCV> { [ Hangul_Hanja ] }; key <LWIN> { [ Super_L ] }; key <RWIN> { [ Super_R ] }; key <COMP> { [ Menu ] }; key <STOP> { [ Cancel ] }; key <AGAI> { [ Redo ] }; key <PROP> { [ SunProps ] }; key <UNDO> { [ Undo ] }; key <FRNT> { [ SunFront ] }; key <COPY> { [ XF86Copy ] }; key <OPEN> { [ SunOpen ] }; key <PAST> { [ XF86Paste ] }; key <FIND> { [ Find ] }; key <CUT> { [ XF86Cut ] }; key <HELP> { [ Help ] }; key <I147> { [ XF86MenuKB ] }; key <I148> { [ XF86Calculator ] }; key <I150> { [ XF86Sleep ] }; key <I151> { [ XF86WakeUp ] }; key <I152> { [ XF86Explorer ] }; key <I153> { [ XF86Send ] }; key <I155> { [ XF86Xfer ] }; key <I156> { [ XF86Launch1 ] }; key <I157> { [ XF86Launch2 ] }; key <I158> { [ XF86WWW ] }; key <I159> { [ XF86DOS ] }; key <I160> { [ XF86ScreenSaver ] }; key <I162> { [ XF86RotateWindows ] }; key <I163> { [ XF86Mail ] }; key <I164> { [ XF86Favorites ] }; key <I165> { [ XF86MyComputer ] }; key <I166> { [ XF86Back ] }; key <I167> { [ XF86Forward ] }; key <I169> { [ XF86Eject ] }; key <I170> { [ XF86Eject, XF86Eject ] }; key <I171> { [ XF86AudioNext ] }; key <I172> { [ XF86AudioPlay, XF86AudioPause ] }; key <I173> { [ XF86AudioPrev ] }; key <I174> { [ XF86AudioStop, XF86Eject ] }; key <I175> { [ XF86AudioRecord ] }; key <I176> { [ XF86AudioRewind ] }; key <I177> { [ XF86Phone ] }; key <I179> { [ XF86Tools ] }; key <I180> { [ XF86HomePage ] }; key <I181> { [ XF86Reload ] }; key <I182> { [ XF86Close ] }; key <I185> { [ XF86ScrollUp ] }; key <I186> { [ XF86ScrollDown ] }; key <I187> { [ parenleft ] }; key <I188> { [ parenright ] }; key <I189> { [ XF86New ] }; key <I190> { [ Redo ] }; key <FK13> { [ XF86Tools ] }; key <FK14> { [ XF86Launch5 ] }; key <FK15> { [ XF86Launch6 ] }; key <FK16> { [ XF86Launch7 ] }; key <FK17> { [ XF86Launch8 ] }; key <FK18> { [ XF86Launch9 ] }; key <FK21> { [ XF86TouchpadToggle ] }; key <FK22> { [ XF86TouchpadOn ] }; key <FK23> { [ XF86TouchpadOff ] }; key <MDSW> { [ Mode_switch ] }; key <ALT> { [ NoSymbol, Alt_L ] }; key <META> { [ NoSymbol, Meta_L ] }; key <SUPR> { [ NoSymbol, Super_L ] }; key <HYPR> { [ NoSymbol, Hyper_L ] }; key <I208> { [ XF86AudioPlay ] }; key <I209> { [ XF86AudioPause ] }; key <I210> { [ XF86Launch3 ] }; key <I211> { [ XF86Launch4 ] }; key <I212> { [ XF86LaunchB ] }; key <I213> { [ XF86Suspend ] }; key <I214> { [ XF86Close ] }; key <I215> { [ XF86AudioPlay ] }; key <I216> { [ XF86AudioForward ] }; key <I218> { [ Print ] }; key <I220> { [ XF86WebCam ] }; key <I223> { [ XF86Mail ] }; key <I224> { [ XF86Messenger ] }; key <I225> { [ XF86Search ] }; key <I226> { [ XF86Go ] }; key <I227> { [ XF86Finance ] }; key <I228> { [ XF86Game ] }; key <I229> { [ XF86Shop ] }; key <I231> { [ Cancel ] }; key <I232> { [ XF86MonBrightnessDown ] }; key <I233> { [ XF86MonBrightnessUp ] }; key <I234> { [ XF86AudioMedia ] }; key <I235> { [ XF86Display ] }; key <I236> { [ XF86KbdLightOnOff ] }; key <I237> { [ XF86KbdBrightnessDown ] }; key <I238> { [ XF86KbdBrightnessUp ] }; key <I239> { [ XF86Send ] }; key <I240> { [ XF86Reply ] }; key <I241> { [ XF86MailForward ] }; key <I242> { [ XF86Save ] }; key <I243> { [ XF86Documents ] }; key <I244> { [ XF86Battery ] }; key <I245> { [ XF86Bluetooth ] }; key <I246> { [ XF86WLAN ] }; modifier_map Control { <LCTL> }; modifier_map Shift { <LFSH> }; modifier_map Shift { <RTSH> }; modifier_map Mod1 { <LALT> }; modifier_map Lock { <CAPS> }; modifier_map Mod2 { <NMLK> }; modifier_map Mod5 { <LVL3> }; modifier_map Mod4 { <LWIN> }; modifier_map Mod4 { <RWIN> }; modifier_map Mod5 { <MDSW> }; modifier_map Mod1 { <META> }; modifier_map Mod4 { <SUPR> }; modifier_map Mod4 { <HYPR> }; };

    xkb_geometry "pc(pc104)" {

    width= 470; height= 180;

    alias <AC00> = <CAPS>; alias <AA00> = <LCTL>;

    baseColor= "white"; labelColor= "black"; xfont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; description= "Generic 104";

    shape "NORM" { corner= 1, { [ 18, 18 ] }, { [ 2, 1 ], [ 16, 16 ] } }; shape "BKSP" { corner= 1, { [ 38, 18 ] }, { [ 2, 1 ], [ 36, 16 ] } }; shape "TABK" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "BKSL" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "RTRN" { corner= 1, { [ 42, 18 ] }, { [ 2, 1 ], [ 40, 16 ] } }; shape "CAPS" { corner= 1, { [ 33, 18 ] }, { [ 2, 1 ], [ 31, 16 ] } }; shape "LFSH" { corner= 1, { [ 42, 18 ] }, { [ 2, 1 ], [ 40, 16 ] } }; shape "RTSH" { corner= 1, { [ 52, 18 ] }, { [ 2, 1 ], [ 50, 16 ] } }; shape "MODK" { corner= 1, { [ 27, 18 ] }, { [ 2, 1 ], [ 25, 16 ] } }; shape "SMOD" { corner= 1, { [ 23, 18 ] }, { [ 2, 1 ], [ 21, 16 ] } }; shape "SPCE" { corner= 1, { [ 113, 18 ] }, { [ 2, 1 ], [ 111, 16 ] } }; shape "KP0" { corner= 1, { [ 37, 18 ] }, { [ 2, 1 ], [ 35, 16 ] } }; shape "KPAD" { corner= 1, { [ 18, 37 ] }, { [ 2, 1 ], [ 16, 35 ] } }; shape "LEDS" { { [ 75, 20 ] } }; shape "LED" { { [ 5, 1 ] } }; section "Function" { key.color= "grey20"; priority= 7; top= 22; left= 19; width= 351; height= 19; row { top= 1; left= 1; keys { { <ESC>, "NORM", 1 }, { <FK01>, "NORM", 20, color="white" }, { <FK02>, "NORM", 1, color="white" }, { <FK03>, "NORM", 1, color="white" }, { <FK04>, "NORM", 1, color="white" }, { <FK05>, "NORM", 11, color="white" }, { <FK06>, "NORM", 1, color="white" }, { <FK07>, "NORM", 1, color="white" }, { <FK08>, "NORM", 1, color="white" }, { <FK09>, "NORM", 11, color="white" }, { <FK10>, "NORM", 1, color="white" }, { <FK11>, "NORM", 1, color="white" }, { <FK12>, "NORM", 1, color="white" }, { <PRSC>, "NORM", 8, color="white" }, { <SCLK>, "NORM", 1, color="white" }, { <PAUS>, "NORM", 1, color="white" } }; }; }; // End of "Function" section

    section "Alpha" { key.color= "white"; priority= 8; top= 61; left= 19; width= 287; height= 95; row { top= 1; left= 1; keys { { <TLDE>, "NORM", 1 }, { <AE01>, "NORM", 1 }, { <AE02>, "NORM", 1 }, { <AE03>, "NORM", 1 }, { <AE04>, "NORM", 1 }, { <AE05>, "NORM", 1 }, { <AE06>, "NORM", 1 }, { <AE07>, "NORM", 1 }, { <AE08>, "NORM", 1 }, { <AE09>, "NORM", 1 }, { <AE10>, "NORM", 1 }, { <AE11>, "NORM", 1 }, { <AE12>, "NORM", 1 }, { <BKSP>, "BKSP", 1, color="grey20" } }; }; row { top= 20; left= 1; keys { { <TAB>, "TABK", 1, color="grey20" }, { <AD01>, "NORM", 1 }, { <AD02>, "NORM", 1 }, { <AD03>, "NORM", 1 }, { <AD04>, "NORM", 1 }, { <AD05>, "NORM", 1 }, { <AD06>, "NORM", 1 }, { <AD07>, "NORM", 1 }, { <AD08>, "NORM", 1 }, { <AD09>, "NORM", 1 }, { <AD10>, "NORM", 1 }, { <AD11>, "NORM", 1 }, { <AD12>, "NORM", 1 }, { <BKSL>, "BKSL", 1 } }; }; row { top= 39; left= 1; keys { { <CAPS>, "CAPS", 1, color="grey20" }, { <AC01>, "NORM", 1 }, { <AC02>, "NORM", 1 }, { <AC03>, "NORM", 1 }, { <AC04>, "NORM", 1 }, { <AC05>, "NORM", 1 }, { <AC06>, "NORM", 1 }, { <AC07>, "NORM", 1 }, { <AC08>, "NORM", 1 }, { <AC09>, "NORM", 1 }, { <AC10>, "NORM", 1 }, { <AC11>, "NORM", 1 }, { <RTRN>, "RTRN", 1, color="grey20" } }; }; row { top= 58; left= 1; keys { { <LFSH>, "LFSH", 1, color="grey20" }, { <AB01>, "NORM", 1 }, { <AB02>, "NORM", 1 }, { <AB03>, "NORM", 1 }, { <AB04>, "NORM", 1 }, { <AB05>, "NORM", 1 }, { <AB06>, "NORM", 1 }, { <AB07>, "NORM", 1 }, { <AB08>, "NORM", 1 }, { <AB09>, "NORM", 1 }, { <AB10>, "NORM", 1 }, { <RTSH>, "RTSH", 1, color="grey20" } }; }; row { top= 77; left= 1; keys { { <LCTL>, "MODK", 1, color="grey20" }, { <LWIN>, "SMOD", 1, color="grey20" }, { <LALT>, "SMOD", 1, color="grey20" }, { <SPCE>, "SPCE", 1 }, { <RALT>, "SMOD", 1, color="grey20" }, { <RWIN>, "SMOD", 1, color="grey20" }, { <MENU>, "SMOD", 1, color="grey20" }, { <RCTL>, "SMOD", 1, color="grey20" } }; }; }; // End of "Alpha" section

    section "Editing" { key.color= "grey20"; priority= 9; top= 61; left= 312; width= 58; height= 95; row { top= 1; left= 1; keys { { <INS>, "NORM", 1 }, { <HOME>, "NORM", 1 }, { <PGUP>, "NORM", 1 } }; }; row { top= 20; left= 1; keys { { <DELE>, "NORM", 1 }, { <END>, "NORM", 1 }, { <PGDN>, "NORM", 1 } }; }; row { top= 58; left= 20; keys { { <UP>, "NORM", 1 } }; }; row { top= 77; left= 1; keys { { <LEFT>, "NORM", 1 }, { <DOWN>, "NORM", 1 }, { <RGHT>, "NORM", 1 } }; }; }; // End of "Editing" section

    section "Keypad" { key.color= "grey20"; priority= 10; top= 61; left= 376; width= 77; height= 95; row { top= 1; left= 1; keys { { <NMLK>, "NORM", 1 }, { <KPDV>, "NORM", 1 }, { <KPMU>, "NORM", 1 }, { <KPSU>, "NORM", 1 } }; }; row { top= 20; left= 1; keys { { <KP7>, "NORM", 1, color="white" }, { <KP8>, "NORM", 1, color="white" }, { <KP9>, "NORM", 1, color="white" }, { <KPAD>, "KPAD", 1 } }; }; row { top= 39; left= 1; keys { { <KP4>, "NORM", 1, color="white" }, { <KP5>, "NORM", 1, color="white" }, { <KP6>, "NORM", 1, color="white" } }; }; row { top= 58; left= 1; keys { { <KP1>, "NORM", 1, color="white" }, { <KP2>, "NORM", 1, color="white" }, { <KP3>, "NORM", 1, color="white" }, { <KPEN>, "KPAD", 1 } }; }; row { top= 77; left= 1; keys { { <KP0>, "KP0", 1, color="white" }, { <KPDL>, "NORM", 1, color="white" } }; }; }; // End of "Keypad" section

    solid "LedPanel" { top= 22; left= 377; priority= 0; color= "grey10"; shape= "LEDS"; }; indicator "Num Lock" { top= 37; left= 382; priority= 1; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Caps Lock" { top= 37; left= 407; priority= 2; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Scroll Lock" { top= 37; left= 433; priority= 3; onColor= "green"; offColor= "green30"; shape= "LED"; }; text "NumLockLabel" { top= 25; left= 378; priority= 4; width= 19.8; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Num\nLock"; }; text "CapsLockLabel" { top= 25; left= 403; priority= 5; width= 26.4; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Caps\nLock"; }; text "ScrollLockLabel" { top= 25; left= 428; priority= 6; width= 39.6; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Scroll\nLock"; }; };

    };

    2017/01/17 Linux.conf.au 2017, Hobart
    π 2017-01-17 01:01 in Linux
    As another full circle LCA, this one came back to Hobart, Tasmania (our last time was in 2009|/perso/linux/post_2009-01-21_Linux_conf_au-2009-in-Tasmania.html].



    As every year, a nice collection of talks












    and of course great parties too:






    And afer a week, it was over, 'till next year:



    See more images for Linux.conf.au 2017, Hobart
    2017/01/16 IoTuz Driver for our ESP32 board built at Open Hardware Miniconf at Linux.Conf.au 2017
    π 2017-01-16 01:01 in Arduino, Linux
    I went to meet the Open Hardware Miniconf team to hang out the previous day and see them at work finishing the last boards:


    last minute hardware patching
    last minute hardware patching


    The IoTuz board was a challenge compared to previous years. It was based on the still new ESP32 and had very little example code. Most of the hardware had never been exercised since the board had been designed, and with a few other people I took the task to heart. Within the week, I was able to get the SPI touch screen working at the same time than the LCD (which required cable select switching via I/O expander lines. It took longer to get the two APA106 (neopixel-like) LEDs to work:

    I had the first etch-a-sketch working :)
    I had the first etch-a-sketch working :)

    So, that all in January. But IoTuz was the gift that kept on giving. It had all those I/O bits that didn't work at all and no one had ever used. Hell, some of them had no existing drivers at all (Neopixel no support under arduino IDE, IO expander needed some access functions, No support for the IR receiver, touch screen needed a few hacks, joystick needed some code to support the huge dead zone in the center), while some other hardware worked out of the box with existing drivers (temp/humidity and accelerometer). The rotary encoder also needed custom ESP32 interrupt code to work properly (nothing too fancy, but there was no existing driver to use).

    So, I embarqued into a mega library/object to support most of the hardware and ended up with almost 1000 lines of code for my IoTuz library, and another thousand lines or so for the main example code (examples/fulldemo) and that does not include 3rd party code of existing demos I was able to re-use and port to IoTuz.

    In the end, that took about 100 hours of work since I had to write/port drivers as I went along, and learn how some of that hardware was even supposed to work :) (ok, non trivial time was also spent finding and chasing platform bugs which have now been fixed, as well as merging driver code with upstream maintainers).

    Here is a quick video summary (longer videos at the bottom):

    And here is the result (thanks to https://github.com/marcmerlin/IoTuz 's examples/fulldemo)

    I made an adjustable touch menu system
    I made an adjustable touch menu system


    drawing circles with the accelerometer by rotating the board
    drawing circles with the accelerometer by rotating the board

    touch color selector
    touch color selector

    hardware scroll of bitmap using the rotary encoder
    hardware scroll of bitmap using the rotary encoder



    Just like the joystick not being very precise or centered right, the touchscreen isn't quite the same for everyone, but especially in my case I broke my touchscreen, had to buy another one and that one was wired reversed, so I designed a screen touch screen calibrator which auto adjusts and supports touch screens that are inversed like mine:


    Enough bla-blah, show me the code: https://github.com/marcmerlin/IoTuz

    And here are some video clips:

    Hardware Intro

    IoTuz Controls

    IoTuz Infrared Support

    IoTuz Demos

    IoTuz Breakout and Tetris

    Again, here's the code: https://github.com/marcmerlin/IoTuz

    2016/10/05 Linuxcon Europe 2016, Berlin
    π 2016-10-05 01:01 in Linux
    For my 3rd and last Linuxcon of the year, I presented my Open Source at Google talk in Berlin, and my talk was well received despite my non ideal delivery due to bad sleeping in the hotel room
    That was my first Linuxcon in Europe, and it was nice to see a different crowd. While the weather in Berlin was pretty crappy, the conference was not :)










    See more images for Linuxcon Europe 2016, Berlin
    2016/08/23 Linuxcon 2016, Toronto
    π 2016-08-23 01:01 in Linux
    After Linuxcon in Japan, we went to the one in Toronto. It had 10 parallel tracks at time, it was a very packed schedule.




    kind of weird to see a keynote on Microsoft showing their 'longstanding' contributions to linux
    kind of weird to see a keynote on Microsoft showing their 'longstanding' contributions to linux


    Funny how microsoft was playing all "we love linux and we have for a long time", when they're still actively extorting money for companies that dare to use linux and aren't paying microsoft windows licenses:

  • http://techrights.org/2016/02/10/extorting-acer-with-patents
  • http://techrights.org/2016/03/10/charm-offensives-distract
  • http://techrights.org/2016/04/29/microsoft-continues-extortion
  • I gave my talk on Open Source at Google and it was well received:


    Show floor:



    The last evening, we had a nice party where people were eoncuraged to dress up:






    ice cream made onsite
    ice cream made onsite

    See more images for Linuxcon 2016, Toronto
    2016/07/13 Linuxcon JP 2016, and my talk on Open Source at Google
    π 2016-07-13 01:01 in Linux
    It was nice to be back at LinuxconJP for another year. This time, I gave a talk about Open Source at Google



    There were other talks and keynotes of course:









    Good times, thanks to all the organizers, volunteers and speakers.

    2016/06/01 Toguard HD 7" Full HD 1080p Android GPS navigation Touch Screen Car Dash Cam Dual lens WiFi
    π 2016-06-01 00:00 in Cars, Linux
    This is a very welcome update to the 5" mirror. You can read my review of the 5" mirror. This is the product link: http://www.amazon.com/Toguard-Mirror-Navigation-Screen-Android/dp/B01FJZ4ZRE

    It is a very welcome update, the older mirror. The camera is nicely integrated now, the screen bigger, and most importantly, the android system has more memory, so you can now easily run other apps like google maps (with the old mirror, you ran out of memory all the time). This is really the update I was waiting for. The old mirror has a super annoying start and stop music and voice. They have now been removed. This is great!

    After connecting to Wifi (2.4Ghz only), you can run google maps or google play store, sign in your google account, and get your saved location searches on google maps (so that you don't have to type them on the mirror, the software keyboard is not very easy to use). As a trick type "ok maps" in the google maps search window, and in most countries, it will download maps for offline use. You can install other apps from the android market, bit it waze, or whatever else you fancy.

    Let's compare the form factor, the mirrors are almost the same size (but the new mirror has nice straps built in), however the main difference is where the display goes. The old mirror put it on the side so that you could read the screen on the left, and see cars behind you on the center and right. The new mirror has a bigger display in the middle and I'm not sure if I prefer that, I think it may be a matter of getting used to it. This is because you're now supposed to look at cars behind you by looking through the display and unfocussing your eyes. It works, but I think you don't see as well. Also, if there is a lot of daylight behind you, the daylight will not make it possible to read the screen (but at least you'll see the cars behind you). I think I kind of prefered the android screen on the side like in the 5" version, but the tradeoff is that you get a small screen which may be harder to read depending on your eyes (I have excellent vision, so in my case I can read both screens fine, but you may not be able to read the 5" one as well):



    this gives you an idea of how you see cars through the screen
    this gives you an idea of how you see cars through the screen

    The camera is built in and more tidy, that's definitely a plus:


    Here are the main points:

  • I have to say again that Toguard/Jeemak US is one of those new Chinese companies that actually cares about customer support and doing the right thing. I have to give them credit for this and hope more companies will do the same. The product is far from perfect, but from my interactions with them, they really care about making it better.
  • The provided written manual is very good. It really is good, kudos for that, especially because how unusual it is for Chinese products.
  • The device is a full featured quad core android tablet in side your rear view mirror. It's still running the older android kitkat which is more memory efficient, and comes with more RAM, so things run smoothly now.
  • You get a real android tablet in a 7" factor. You can add our google account, install google maps or waze and you could even install calendar or gmail if you wish.
  • The wifi is 2.4Ghz only and would be used to install apps at home, or tether to your phone, but that's a bad choice because wifi tethering is very expensive on batteries for your phone. Still, it's better than nothing, and ok for you if you have a fancy car that provides its own wifi hot spot.
  • The unit ships with sygic and polnav mobile. Polnav didn't seem to really work or have data I could get for the US, but sygic seems like a good navigation app that works offline. You can also use google maps offline if you wish. Too bad you cannot tether via bluetooth.
  • While you cannot use the missing bluetooth to route audio from the mirror to your car, it comes with an FM transmitter, so you can route audio to your car radio.
  • The rear camera is low quality, but I'll take that over nothing, it can come in handy if you get hit from behind, it will do fine to prove that. The front camera in the 7" mirror looks bigger and better, but in my testing conditions, it didn't so very well for capturing license plates of moving cars. I think the lighting conditions were non optimal and caused this because I've seen a video from someone else taken by the same camera, and it was much better quality than what I captured. This is another way to say that you should expect better quality in some conditions than what I posted.
  • The GPS is a great addition for the base price (many dashcams do not include it by default). First I thought mine wasn't working well, until the nice Toguard support told me that it had to be mounted with with glue sticker facing down (I had glued it to my windshield next to the mirror, which meant it was upside down).
  • The device comes with about 16GB of flash free, which is very generous, and handles external sdcards perfectly. Flash is used to install android apps, and video recording is done on the external sdcard.
  • Toguard removed the stock android settings app, which arguably is a bit complicated and replaced it with a custom settings app that has just the basics
  • Downsides:

  • The flipside of the custom settings app is that it lacks advanced settings that android enthusiasts may like. But for instance this has caused issues with timezone settings (you have to manually change the time for the timezone you're in). Similarly, you can't install a new keyboard from android market and switch to it since you can't access the settings. To be fair, average users won't care and will probably be happier with the simplified but limited settings app.
  • The android status bar where you can find quick settings and info from some apps, is gone. Average users won't care, power users of android might.
  • The unit is flashable, so in theory you can install new firmware, but it requires a complicated procedure using customized windows software (I tried that while reviewing an early version of the hardware). I expect that it will likely not be end user upgradable.
  • The video recorder works fine, but it does not allow changing EV settings, nor can it be used as a parking camera with motion detection.
  • There is no more hardware menu key. You cannot long hold the menu key to switch apps, you have to go back to home, select the app and switch. Not a huge deal, but it's slower if you switch apps often.
  • Sadly it does not come with bluetooth. Bluetooth would have been a perfect way to get internet from your phone via bluetooth tethering without killing your batteries. While having callers show up on BT could be useful for some, most cars do this now, so I don't really need that feature, and the audio from that mirror isn't great anyway.
  • The rear camera wire is not good though because it contains a big adapter bulge in the middle which makes it impossible to route inside your car due to how thick that bit is.
  • The rear camera is only 480p and poor quality but it will read a place from a car that is stopped behind yours. If any car is moving, the picture will be unusable for license plates but good enough to see that someone else hit you (it is mostly the same camera than the older 5" mirror).
  • The rear camera has a red wire you're supposed to connect to your rear headlights. This is however difficult to do on my car, and I wish they had just used a light sensor to remove the extra wiring requirement. In my testing, I did not wire the night vision LED, although to be honest, I doubt they can do much except maybe to video the outline of someone who would come on foot to break your rear window. If you're driving, headlights from cars behind you totally overwhelm the camera.
  • Because the hardware does not support motion detection, wiring to always on power is not very useful.
  • So, my verdict?

  • If you are looking for a mirror that can run android apps and you are ok with a very well integrated dual dashcam, to show that the other car hit you, and you didn't reverse into it, this will work. If someone who does a hit and run on you stops before driving off, you may not get their plate. If you're hoping to get the plate from someone who cut you off, it may or may not work for that depending on lighting conditions
  • If you want best video quality and don't need dual cam, the Wheel Witness HD Pro is the best one I've seen so far, read my review, but keep in mind that it's a big single dashcam without android.
  • If you don't really want/need to add 3rd party android apps, and all you want is a basic dual cam rear view mirror, then the old 5" will likely work just as well for you while having the advantage of keeping the screen separate from the mirror area you use to see cars behind you
  • But to repeat myself, if you're looking for a smart mirror that can run android apps while also being a dual dashcam. This device is definitely best in class today. You should be happy with it.
  • Shots from the camera:

    in some cases of moving cars, you can barely read the plate
    in some cases of moving cars, you can barely read the plate

    most times, it's almost readable, but not quite
    most times, it's almost readable, but not quite

    same here
    same here

    low speed, close to car, but not close enough
    low speed, close to car, but not close enough

    finally
    finally


    More pages: March 2018 January 2018 September 2017 January 2017 October 2016 August 2016 July 2016 June 2016 February 2016 January 2016 May 2015 March 2015 January 2015 October 2014 May 2014 April 2014 March 2014 January 2014 November 2013 September 2013 May 2013 March 2013 January 2013 December 2012 August 2012 May 2012 March 2012 January 2012 December 2011 August 2011 July 2011 January 2011 October 2010 August 2010 June 2010 April 2010 March 2010 January 2010 December 2009 November 2009 September 2009 August 2009 July 2009 May 2009 January 2009 December 2008 November 2008 October 2008 January 2008 November 2007 August 2007 July 2006 January 2006 August 2005 April 2005 November 2004 March 2004 February 2004