Wednesday, 10 March 2021

Turning laptop into a keyboard: USB CDC Serial port to USB HID Keyboard Emulator

 Why on earth would I want to turn my laptop into a keyboard & monitor for another computer? It is easier to buy a usb keyboard and mobile monitor. Indeed I did exactly that. Years of dutifully humping keyboard, monitor, laptop and toolbox makes you dream of lightening the load. After all, the laptop already has a keyboard and screen; why carry more?

Most of the time I log into the onsite computers remotely via ssh (Teamviewer for Windows), but sometimes you need to debug the POST process or change the BIOS settings, before your OS is running.

Serial to USB HID Keyboard Emulator

My solution is to use a USB framegrabber for the monitor and a USB keyboard emulator. 


Watch video demo on youtube


You can of course buy a UART to USB Keyboard Converter like Inteletto's. 

Interletto RS232 to USB Keyboard cable


You can even build a superior one using the Bluefruit EZ-Key.  But the Inteletto costs USD99 and the EZ-Key (USD20) is discontinued. and I already have the parts to build my own.



Enter the Microchip PIC18F14K50. More importantly the free USB source code in MPLAB. I used my own miniaturized, code-compatible version of the Microchip Low Pin Count Development Kit

Microchip PIC18F14K50 Low Pin Count Development Board


Miniaturized PIC18F14K50 Low Pin Count Development Board 


The schematics is in the User Guide. Unlike the Bad Old Days there is even a Linux version of MPLAB now. My programmer is a PICkit 2.

Low Pin Count Development Board schematics

PICKit 2 Programmer (bottom)


The idea is to use two Low Pin Count Development boards connected back-to-back via Serial TTL or RS485; one programmed as USB CDC Serial Port and the other as USB HID Keyboard.

Two PIC18F14K50 boards back-to-back connected via 2-wire RS-485

You plug the serial port into your development system (ie main computer) and in a Linux system it comes up as /dev/ttyACM0. For Windows user, there is a device driver in the MPLAB library. You point minicom to /dev/ttyACM0, set the baudrate to 19200 1-stop no parity with no hardware flow control. You plug the USB 'Keyboard' into the target computer. Keys typed into minicom appears at the other end, the USB Keyboard.

Now this sounds expensive but a stripped-down and miniaturized PCB for is quite cheap to make, even in small quantities, and the PIC138F14K50 (SOIC-20 package) is only RM11 (USD2.76) at Digikey. You can also use any standard USB serial dongle, like the CH340. 

CH340 USB Serial TTL Dongle


I settled on the venerable ASCII as the serial protocol. It is easy to debug. This means minicom sends ASCII to the keyboard UART and this then needs to be translated to the corresponding USB Keyboard scancode. 

Full ASCII table

You can get the USB HID Keyboard whole nine yards from usb.org, but I used a handy summary from MightyPork

A small part of USB Keyboard scancodes

For example, ASCII code for 'A' is (hexadecimal) 0x41 and this is translated to 0x04. The software is a slightly modified version of Microchip's source code from the Low Pin Count Development Kit. A similar (but not identical) version is Microchip/USB/Device - HID - Keyboard/Firmware/Keyboard.c

You can download the file from my github repository. Notice my code uses a MAX323 RS485 to TTL converter IC, but this should be compatible with the schematic above. Minicom actually does not have enough keys to emulate a full-sized USB keyboard, so what you have here is a minimum subset of keystrokes needed to sucessfully change a BIOS. For example, the CapsLock key is emulated as 'Ctrl-N'. Other notable mappings:

CapsLock - Ctrl N
Ctrl-Alt-Del - Ctrl O
F1 - Ctrl Q
F2 - Ctrl R
F5 - Ctrl S
F6 - Ctrl T
F9 - Ctrl U
F10 - Ctrl V
Left Arrow - Ctrl W
Down Arrow - Ctrl X
Right Arrow - Ctrl Y
Up Arrow - Ctrl Z

If you do not have access to MPLAB there is a binary file keyboard.hex compatible with the PICKit 2.

To compile, I ran MPLAB from a qemu-kvm Virtual Machine running Windows XP. Using puTTY I sshfs into the MPLAB working directory to extract the binary file for programming.
 
$ sshfs -o reconnect -C user@12.34.56.78:c:/Program\ Files/ICW/home/user/keyboard/USB\ Device\ -\ HID\ -\ Keyboard/Firmware $HOME/pic18f14k50/keyboard/source

$ cp source/*.hex .

I use pk2cmd to program my PICkit 2:

PICkit 2 mounted on JTAG programming port


$./pk2cmd -PPIC18F14K50 -Fkeyboard.hex  -M 
PICkit 2 Program Report
7-3-2021, 14:57:12
Device Type: PIC18F14K50

Program Succeeded.

Operation Succeeded

There you have it- USB CDC Serial to USB HID Keyboard simulator. Happy Trails.