colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

PS/2 keyboard driver in assembler

Mon Feb 03, 2014 8:00 pm

(or "Is USB the most obnoxiously insane standard ever?")

I've got my PS/2 driver nearly finished. It deals with nearly all keys (ie. also FN and cursor keys, Home/End, PgUp/PgDn etc, CTRL, ALT and SHIFT modifiers). I'm still ignoring PrtScrn and Pause/Brk -- but they're not doing anything unexpected. And I'm not dealing with the Windows modifier yet. Nor have I looked at sending commands to the keyboard.

The object file (ps2.o) is currently a bit under 5000 bytes but adding functionality might lower that a bit :-) At the moment it just puts the characters in a buffer. CTRL is a bit set in the char and cursor/movement keys have a different code when shifted, so you can do CTRL-SHIFT-(any key) which puts a single byte in the buffer and causes an interrupt.

I haven't set up a git repository yet because I've got a headache :-(
Last edited by colinh on Fri Feb 07, 2014 12:56 am, edited 1 time in total.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: PS/2 keyboard driver in assembler

Thu Feb 06, 2014 1:19 am

Headache is mostly gone, but I've got my first brand new super duper DSO/MSO so... :oops:

In the meantime, I've thought a little about the PS/2 keyboard protocol. And it's weirdnesses.

It's not as insane as USB, but it was created by the same people that came up with EBCDIC (and FUD) so it's still nuts.

As one guy put it...
This would be a very nice serial protocol if it wasn't for the computer, which occasionally wants to send information to the keyboard.
<describes pulling CLK low etc.>
This would still be a nice protocol if it wasn't for some special keys present on the standard PC keyboard, like Home, End, the arrows, etc
<goes on to explain the special extended modifier 0xE0 thing...>
To make [this] story a bit more complicated, two super-special keys exist, Print Screen and Pause, which cause a whole sequence of scancodes to be transmitted. For a keyboard interfacer, it's best to pretend these keys do not exist.
:lol:


For anyone who wants to pretend that these keys do exist...

... a sane person might think that the protocol was "designed" by several different humanoids, who didn't talk to each other. Two of these guys had only one key each to do. The result being a cock-eyed mess.

The extended scancode keys are basically that bunch in the middle: the INS/DEL, HOME/END, PgUp/PgDn. And the cursor (aka arrow) keys. These are all simply E0 versions of their counterparts on the keypad. Then keypad-Enter and keypad-/ are E0 versions of normal Enter and '/'. Keypad-<+- and *> have normal codes (*shrug*), while R-ALT and R-CTRL were an afterthought. So they're E0 of the left version.

This is all clear. The two weird keys seem crazy though.

However, if we imagine (in a process a little bit like unifying the laws of electricity and magnetism and then even the weak nuclear force) that there's a special alternative shift key above the keypad, said shift key generating scan code 0xE012 (instead of 0x12 for the normal (left) SHIFT key) then pressing/releasing PrtScr is equivalent to

press WEIRDSHIFT, press PRINT, release PRINT, release WEIRDSHIFT.

The PRINT key doesn't exist. It generates 0xE07C. Scancode 0x7C does exist – it's keypad-*.


The Pause/Brk guy thought of something else...

He didn't know about the secret WEIRDSHIFT key. Actually, maybe he did know about WEIRDSHIFT and thought it was stupid – so he generated an entirely new set of extended scancodes prefaced with E1 instead of E0 (needed for his SUPERWEIRD-CTRL key). So, instead of WEIRDSHIFT extendedNUMLOCK we have

Press SUPERWEIRD-CTRL, press NUMLOCK, release SUPERWEIRD-CTRL, release NUMLOCK.

Why release the super-extended L-CTRL before the NUMLOCK? I don't know. In any case, he thought that users wouldn't be able to release the key on their own, and so he coded that weird release sequence into the key-press sequence.

Maybe Pause/Brk used to be on NUMLOCK (the way CURSOR-LEFT is on keypad-4) and PrtScr used to be on keypad-*. Maybe they thought that having a special extended L-SHIFT key only for PrtScr and a special super-extended L-CTRL key only for Pause/Brk was a bit stupid and so they rationalised them, by replacing them with two different keys...

Anyway, as you see, it all makes perfect sense after all.

rst
Posts: 494
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: PS/2 keyboard driver in assembler

Thu Feb 06, 2014 11:06 am

colinh wrote:(or "Is USB the most obnoxiously insane standard ever?")
No, it isn't.

It's a big standard but you can do a lot of things with it. For instance creating a $35 Linux computer which connects to many different devices at the same time with a single connector.

Rene

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 12:13 am

I admit it is a standard. But that doesn't mean it's a good one. Where "good" is, of course, highly subjective.

But there are also objective measures such as:
a) overhead
b) ease of implementation
c) resulting size of implementation

IIRC it took years before you could expect a Linux box to "do the right thing" when you plugged an arbitrary USB device in. If it were so wonderful, why would FTDI be so successful with its FT2232 chips? The ones that interface (yes) USB to, effectively, RS232.

I believe one could have come up with a simpler standard for serial data transfer. Even one that lets a device say "I'm a joystick" or "I'm an x, but treat me as a mass storage device".

So, IMHO, the only good thing about USB is that it is a standard.


EDIT:

For comparison, AFAIK the ONLY person who has managed a bare metal USB keyboard driver is Alex Chadwick. According to him it was painful and took weeks. He doesn't recommend reading the 800 page manual. His driver polls, because, for one reason or another, he couldn't get at the interrupts. His library is about 34k (stripped).

My PS2 keyboard driver: knocked up in a couple of days. Used a webpage of "documentation". Uses interrupts. Is under 1.5k (stripped). And it's only that big and took that long because the PS2 standard is also, ummm, well – by IBM.

Of course, everyone knows that implementing a UART sort of protocol is trivial. And no, my keyboard driver doesn't talk to my phone. Or my fridge. But then, neither does Alex's :)

User avatar
jojopi
Posts: 3409
Joined: Tue Oct 11, 2011 8:38 pm

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 1:49 am

colinh wrote:Maybe Pause/Brk used to be on NUMLOCK (the way CURSOR-LEFT is on keypad-4) and PrtScr used to be on keypad-*.
Pretty much. The original PC keyboards had 83 or 84 keys. When the extra keys were added they were made to send E0 plus the code of their existing counterpart, so that old systems would ignore the prefix and still do something sensible.

But PrtSc was originally Shift+Keypad*, so the new dedicated PrtSc key has to pretend to press Shift. Using a prefixed Shift code allows newer software to tell it is a fake.

Pause was originally Ctrl+NumLock, and Break was Ctrl+ScrollLock. Because there is already both original left Ctrl and E0-prefixed right Ctrl, fake Ctrl uses E1 prefix.

SysRq was originally a dedicated key, so you should find that Alt+PrtSc sends a simpler code than PrtSc alone.

The PS/2 introduced a new, logical, set of scan codes. However, no major OS ever switched the keyboard to set 3, so its implementation is missing or buggy in many keyboards. For more details see: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 4:39 am

I didn't really think it was designed by deranged monkeys :)

Backwards compatibility is a tricky thing. When a company (like Apple) doesn't give two hoots about it, making minimal changes to libraries for the fun of it, removing compatibility libraries and emulators just like that, telling me that I have no use for an optical drive, a firewire port, ethernet, modem(*), cardbus-slot, serial/parallel port well, then I get annoyed too :evil:

It looks like some early keyboard also had a larger number pad with hex input keys (A-F), because there are exactly 6 scan codes missing between 0x69 ("1") and 0x7C ("*"). Actually, I'd quite like a keyboard with a number pad like that...

(*) OK, I admit I don't need this any more.

rst
Posts: 494
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 9:18 am

colinh wrote:I admit it is a standard. But that doesn't mean it's a good one. Where "good" is, of course, highly subjective.
OK, you don't like it. No problem. But you used some strong words about it. I was a little bit involved in the early times of USB. This was a big community and maybe still is it. Those people were not "insane" and neither is their standard.
But there are also objective measures such as:
a) overhead
I think it was time for a more general approach when developing USB. The PS/2 interface is a standard of the 80th. USB of the late 90th and still. When you want a general solution for a great variety of devices you will inherently get more overhead than for a single device class.
b) ease of implementation
Yes, USB is a big hardware and software system and it took time to develop it. I think the time is over that a single person can write a host controller interface (HCI) driver from scratch for such system in one week. Software systems are getting bigger today.
IIRC it took years before you could expect a Linux box to "do the right thing" when you plugged an arbitrary USB device in.
But than you could attach a bunch of devices and they were basicly able to communicate with the host. You would need to develop only a small driver for your special device class to do it all.
If it were so wonderful, why would FTDI be so successful with its FT2232 chips? The ones that interface (yes) USB to, effectively, RS232.
I think RS232 is mostly a standard to attach a terminal-like device. There is still need for this. With USB you can attach fairly most devices (also terminals). This is different.
For comparison, AFAIK the ONLY person who has managed a bare metal USB keyboard driver is Alex Chadwick. According to him it was painful and took weeks. He doesn't recommend reading the 800 page manual. His driver polls, because, for one reason or another, he couldn't get at the interrupts. His library is about 34k (stripped).
I know it is possible to develop an own bare metal USB HCI driver. I did it on the PC (UHCI, EHCI) and on the Raspberry Pi. I think it took about two month to port my hobby kernel including USB from the PC to the Raspberry Pi and I was completely new on the ARM.

The USB HCI driver was mostly written from scratch with insight into Alex Chadwick's driver and the Linux driver. I can use a keyboard, an USB mass storage device (USB stick) and the network interface device. My driver uses interrupts and interrupt transfers (for the keyboard). I think the size of the driver is not a problem anymore.

Rene

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 8:05 pm

rst wrote:OK, you don't like it. No problem. But you used some strong words about it. I was a little bit involved in the early times of USB. This was a big community and maybe still is it. Those people were not "insane" and neither is their standard.
My apologies. Of course they're not insane. And USB is useful these days in the real world. I was ranting from an amateur bare-metal perspective.

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 8:23 pm

@by colinh,
How are you interfacing your ps/2 keyboard, to your pi ? (gpio) etc.
And have you some test code ?.
Also have you tryed your driver with a usb keyboard and usb to ps/2 adapter ?.

PS: I do agree USB is a pain for hobby OS Dev, when there's no data sheets released.
Batteries not included, Some assembly required.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: PS/2 keyboard driver in assembler

Fri Feb 07, 2014 10:31 pm

I'm using one tiny Level Converter from sparkfun.

It converts two inputs at 5 V to outputs at 3.3 V and two inputs at 3.3 V to outputs at 5 V too. (That's two twos, two tos and a too too :) )

I'm not using the 3.3 -> 5 V side yet (to talk to the keyboard).

I have another Level Converter for the mouse, but haven't got round to that.

I, ummm, chopped the ends off of the PS/2 keyboard and mouse and crimped 2.54 mm post connector sockets (?) on them.

I think you can get a dual PS/2 socket + bidirectional level converter, which is probably a better way of doing things :)

I soldered a post connector at header P5 (but on the upper board side - so the pin numbers are swapped even-odd)

That header is now

1 - 3.3 V
2 - 5 V
3 - KBD_CLK
4 - KBD_DATA
5 - MOUSE_CLK
6 - MOUSE_DATA
7 - GND
8 - GND


I haven't tried a USB to PS/2 adapter. I don't have one. But I presume it would work.


I'm just tidying the code up (making comments more generally understandable. Consistency etc). I'll put it up somewhere soon (or let you have a copy directly).

rst
Posts: 494
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: PS/2 keyboard driver in assembler

Sat Feb 08, 2014 6:05 am

colinh wrote:My apologies. Of course they're not insane. And USB is useful these days in the real world. I was ranting from an amateur bare-metal perspective.
OK. No problem anymore. :-)

Rene

User avatar
rpdom
Posts: 18021
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: PS/2 keyboard driver in assembler

Sat Feb 08, 2014 6:15 am

That's a nice bit of work you've done :)

I started down a similar route last year. I used a PS/2 socket from an old PC motherboard and a couple of simple resistor dividers to handle the 5V->3.3V conversion (I didn't bother with the 3.3V->5V side as I didn't need to talk to the keyboard for the project I was working on).

I didn't think about using the P5 connector as my main Pi is a Rev 1 Model B, but I was doing the dev work on a Model A so I should switch to using that.

I managed to get a simple interrupt-driven driver (mostly) working, but got distracted with another project - emulating a BBC Micro mode 7 screen in bare-metal complete with flashing cursor and text :)

Then work got in the way :(

User avatar
DexOS
Posts: 876
Joined: Wed May 16, 2012 6:32 pm
Contact: Website

Re: PS/2 keyboard driver in assembler

Sat Feb 08, 2014 8:04 pm

colinh wrote:I'm using one tiny Level Converter from sparkfun.

It converts two inputs at 5 V to outputs at 3.3 V and two inputs at 3.3 V to outputs at 5 V too. (That's two twos, two tos and a too too :) )

I'm not using the 3.3 -> 5 V side yet (to talk to the keyboard).

I have another Level Converter for the mouse, but haven't got round to that.

I, ummm, chopped the ends off of the PS/2 keyboard and mouse and crimped 2.54 mm post connector sockets (?) on them.

I think you can get a dual PS/2 socket + bidirectional level converter, which is probably a better way of doing things :)

I soldered a post connector at header P5 (but on the upper board side - so the pin numbers are swapped even-odd)

That header is now

1 - 3.3 V
2 - 5 V
3 - KBD_CLK
4 - KBD_DATA
5 - MOUSE_CLK
6 - MOUSE_DATA
7 - GND
8 - GND


I haven't tried a USB to PS/2 adapter. I don't have one. But I presume it would work.


I'm just tidying the code up (making comments more generally understandable. Consistency etc). I'll put it up somewhere soon (or let you have a copy directly).
Thanks for the info, i already have the "Level Converter from sparkfun" and about 500 ps/2 sockets, as i was going to make pcb for this.
If anyone wants to make the pcb, let me know i will send them the socket if they in the UK .
And look forward to testing your code.

PS: I am not sure if you have seen it, but i converted the Alex Chadwick USB code to ASM here: http://www.raspberrypi.org/phpBB3/viewt ... 10#p476310
Batteries not included, Some assembly required.

colinh
Posts: 95
Joined: Tue Dec 03, 2013 11:59 pm
Location: Munich

Re: PS/2 keyboard driver in assembler

Sun Feb 09, 2014 9:21 pm

OK, I've finally created my very own git repository

https://github.com/colin2/RPi

Oh, I have tabstops set to 4 spaces in vi - so the formatting looks off.

Return to “Bare metal, Assembly language”