Replacing the Model M controller board with a Pi Zero.
(Alternate title: How to use up 24 GPIOs.)

Similar projects worth following
The Pi Zero has enough GPIOs to completely replace the Model M keyboard controller. I'll show you how I installed it and added software to turn it into a USB keyboard. Enterprising individuals should be able to use this as a starting point to turn it into a Bluetooth or WiFi keyboard.

This same technique and software could be used to embed a Pi in some other keyboard or computer that has a matrix keyboard, for instance a Commodore 64.

NOTE: No Model M keyboards were harmed in this project. That would be horrible. The modifications detailed herein are completely reversible.


I decided to put a Zero in my beloved Space Saving Model M keyboard: that's the sort of thing everyone does, right? It shouldn't be too hard - stuff the Zero in there (there's lots of room!), and connect it to the keyboard's controller board using this circuit. Why would I do this, you ask? Because, using the Pi Zero, I could. I'd figure out what I could use it for later!

Then I had an epiphany: the Zero has enough GPIOs to completely REPLACE the keyboard controller. I'd just need to write a kernel module to scan the keyswitch matrix. Since I'd already done about half the necessary work on a previous project, it shouldn't take too long. And as an added bonus, it would consume less than half the current of the original keyboard controller. That would make battery operation possible. And any project that uses 24 GPIOs on a Pi has got to be awesome, right? I could even spin it as "upgrading the Model M keyboard controller" instead of the rather pedestrian "Pi stuffed inside of a keyboard". Bonus!


So I started by writing a kernel module. I decided to write it as a generic switch matrix handling module, in case other people might find it useful. Maybe someone will want to put a Pi inside of a Commodore 64 or something? (Comments are in the source if you want to do this.) Of course I used my favourite switch de-bounce routine. I got basic matrix scanning with n-key rollover working, and started on ghost key lock-out. Then I had a terrible thought: the Linux kernel probably already has a switch matrix module. And sure enough, a quick search turned up the matrix_keypad kernel module.

Oh no, I thought, all that work was for naught!

I went through the matrix_keypad module code to see how it worked. As far as I could tell, it used a simple time delay to de-bounce the switches, not a robust filtering algorithm like mine. And I couldn't find any ghost key lock-out. It gave me the feeling that it was written for small switch matrices, not a full keyboard. It did have the advantage of being interrupt-on-change driven, unlike mine which uses a regular timer tick. So the crisis was averted - my module was definitely better for a full keyboard! I added ghost key lockout to my module, double-checked the translation table, and it was done. I made a device tree overlay for it, and added a reference to it in /boot/config.txt.


Now that the keyboard was working I really needed to figure out what I would use it for. I could use it as a USB keyboard using the USB HID gadget driver. Or a Bluetooth keyboard using a Bluetooth dongle. Or even a WiFi keyboard using a WiFi dongle, so I wouldn't have to add Bluetooth to my Pi 2. (These last two would require batteries of course.) Or even all three, with the mode determined by what was plugged into the USB port! But in the end I decided to concentrate on first making it a simple USB keyboard. Then I wouldn't have to worry about batteries.

That meant I'd need to use the g_hid (HID gadget) kernel module. I thought it'd be simple to get it working, but upon researching it, I found that it needed a data block in HID report format sent to it's device file. And those reports are completely different from how Linux reports keyboard events. The Linux event system sends key-up and key-down events, and the HID report consist of the modifier key states (in a bitmap) followed by the keycodes of up to 6 keys that are currently pressed. These reports are sent only when there is a change in key state. So I wrote a userspace program (called event2hid) to get key events, map which keys are down, and scan this map (when there was a change) to generate and write a properly formatted HID report. Oh, and also translate the key codes since they're completely different!

On top of that, the g_hid kernel module didn't work! It...

Read more »


Linux 4.4.1+ module files

gzip - 15.40 MB - 04/19/2016 at 20:34



Linux 4.4.1+ kernel and suport files

gzip - 14.57 MB - 04/19/2016 at 20:34



custom init program

mini-init - 5.62 kB - 04/19/2016 at 20:34


custom init shell script

Bourne Shell Script - 727.00 bytes - 04/19/2016 at 20:34



custom init program source

C Source File - 1.17 kB - 04/19/2016 at 20:34


View all 13 files

  • 1 × 22K 8-resistor bussed array, Digi-Key 4609X-101-223LF
  • 1 × 8-pin connector, Digi-Key 5-520315-8
  • 1 × 16-pin connnector, Digi-Key 6-520315-6
  • 9 × 5" lengths of wire wrap wire

  • Pi Zero W to the rescue

    mincepi03/04/2017 at 01:21 0 comments

    I was looking for a project for the Pi Zero W I bought a couple of days ago when it dawned on me that I had planned a Bluetooth option for this project. So that's what I'll use it for. Then I'll have a wireless keyboard for my Pi 3 I received for Christmas!

    I also need to finish converting this project to configfs so I don't need a custom kernel module. It's becoming a pain to compile and upload them.

  • fixed a bad link

    mincepi08/02/2016 at 02:35 0 comments

    Fixed a bad link to the LinuxQuest forum.

  • image uploaded

    mincepi04/23/2016 at 02:10 0 comments

    Uploaded an image file for easier setup. Added instructions for it.

    Also marked project as done, even though I may add functions in the future.

  • initial posting

    mincepi04/19/2016 at 21:12 0 comments

    Initial posting. Mostly copied from the project page on my website.

View all 4 project logs

  • 1
    Step 1

    Read through how I built mine in the project description. The pictures show almost all you need to know, and the text tells you the rest. Read it carefully - there are some important details you might miss. And definitely read it all the way through first!

    Build it exactly like I did with the following changes:

    • Instead of a mounting plate use silicone caulk to attach the Zero to the keyboard base. Make sure that there's plenty of air circulation around the processor chip, with no caulk touching it.
    • It's easier to just glue the USB socket down with silicone caulk instead of making a mounting plate.
    • You can make a A-A cable by cutting two USB cables off some old keyboards, and splicing like colors together. Keep the splices short, there are high frequencies involved. Or just buy a cable, but make sure it's wired correctly. There is no standard in the USB spec for A-A cables. Or forget the whole socket thing and wire a cut off keyboard cable directly into the Zero. This locks you into USB mode however.

    PRO TIP: Model Ms use a weird screw size - 5.5mm (7/32") that's in a deep recess. I had to turn down a nut driver bit to fit.

    NOTE: USB color codes are pretty standard, so wire your USB socket like the picture and hope for the best. Be sure to keep the white and green wires short and the same length. Those solder pads are quite close together so be mindful of shorts. I recommend you do like I did - check the red wire polarity before soldering it. Finally, a little hot glue around the connections is a good idea.

    Download this image, extract it, and copy it to an SD card using dd just like you'd do with a Raspbian image. Note that it's compressed with gzip so you can't do this on Windows. Any card 2G or bigger should work. After it's done load the SD card in the Zero and boot it up. Everything should work.

    If you want to do it the hard way, follow these steps:

    As of this writing, the mainline Raspbian kernel doesn't support gadget mode. The easiest way to fix this is to download (from the files section) the modules.tar.gz file and extract it in /lib/modules, and the kernel.tar.gz file and extract it in /boot. This will get you booting into kernel 4.4.1+, which supports gadget mode. Then download the rest of the files from the files section and place them as follows:

    g_hid.kogoes in


    matrix2pi.kgoes in/lib/modules/4.4.1+

    event2hidgoes in/etc

    mini-initgoes in/etc

    mini-init.shgoes in/etc

    matrix2pi-overlaygoes in /boot/overlays

    add init=/etc/mini-init to the end of the

    /boot/cmdline.txt file.

    add dtoverlay=dwc2 and dtoverlay=matrix2pi to the /boot/config.txt file.

    Reboot, and if I haven't forgotten anything, it should work. To get back to a usable state for troubleshooting, comment out the tvservice line in /etc/ and remove the init entry in /boot/cmdline.txt. Of course you'll have to do these by putting the SD card in another system: I call it "Doing the SD card shuffle.".

    Happy hacking!

View all instructions

Enjoy this project?



Dustin wrote 10/22/2018 at 18:08 point

If you put a decent sized battery in it, you could just leave the Pi running all the time and have it charge over USB if possible. I'm sure there are flaws with that plan, but can't think of them. Any thoughts?

  Are you sure? yes | no

Dustin wrote 10/22/2018 at 18:02 point

I just got a beautiful Model M at a pawn shop for $5 and am so anxious to start using it. PS2 interface, not AT. I wanted to just get an adapter, but I read that doesn't work so well. I was going to just add a Teensy, but wanted to replace the original driver board and be able to restore it to original if needed. I love your project. I'll be using it to get my keyboard working. I plan to cram an Intel Compute Stick PC into the keyboard, and use Chromecast to cast the desktop out to a display. I'll add an HDMI port and as much battery power as I possibly can. Your project here is the missing piece to my upcoming project. Thank you for your hard work and sharing it. 

  Are you sure? yes | no

Terry Daniels wrote 04/21/2016 at 01:26 point

A lot of motherboards (Mine for example) can power the device when the computer is "shut down" so I guess you could use that to put the keyboard in a sort of standby mode. Also if the pi zero hardware supports hibernation, that might help. Anyway, I love this project, and am thinking about doing something similar myself.

  Are you sure? yes | no

mincepi wrote 04/21/2016 at 16:34 point

Yes, that would mean you wouldn't need to do the custom init thing.

I only switched to a custom init after testing the keyboard on a Pi 2: when the Pi 2 (and probably the B+) powers down, it cuts power to the USB ports, even though 5V power is still connected. I wasn't expecting that. I had thought that a magic key sequence on the keyboard that did an orderly shutdown would be enough.

Let my know if you need any help on your project. I didn't make a big deal about it in the write-up, but the matrix scanning routine is easily customized for any dimension of matrix, only limited by the number of GPIOs on the Pi.

  Are you sure? yes | no

Terry Daniels wrote 04/21/2016 at 16:52 point

That's pretty awesome :) thanks man. and good luck with your ongoing projects!

  Are you sure? yes | no

Yann Guidon / YGDES wrote 04/19/2016 at 21:30 point

Now this question might become a thing : "how long does it take to boot a keyboard ?" :-D

  Are you sure? yes | no

mincepi wrote 04/20/2016 at 01:45 point

Ha ha!

Less time than the computer it's attached to takes to boot?

Okay, the real answer: I don't have the capability to directly measure boot time since the keyboard is sealed up right now. But it takes 7 seconds from plugin to usable on Linux, 11 seconds for Win7.

I did say that my mini-init speeds up the boot time, didn't I?

  Are you sure? yes | no

Yann Guidon / YGDES wrote 04/20/2016 at 01:50 point

7 seconds is interesting ! I have to check this method ;-)

But is it fast enough to allow you to jump at the POST messages to get into BIOS config mode ? :-P

  Are you sure? yes | no

mincepi wrote 04/20/2016 at 01:57 point

My recent HP BIOS doesn't like it.  But once you've entered BIOS setup, it works OK.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates