This video demonstrates how to implement a keyboard driver in a custom operating system by creating an interrupt handler class that responds to keyboard interrupts (IRQ 0x21), reading key codes from the keyboard's data port (0x60), and properly acknowledging interrupts to the Programmable Interrupt Controller (PIC) to enable continuous hardware communication. The tutorial shows how to transition from static interrupt handling to object-oriented design using an interrupt handler base class, and explains the challenges of USB keyboard support requiring BIOS legacy support settings.
Write Your Own Operating System 6: Keyboard Interrupts | Kernel Dev Tutorial Part 6
Added:hello and welcome back to the sixth part of the tutorial on writing your own operating system so where were we in the last video so if this is your processor and here's your programmable interrupt controller and this is connected to for example is a keyboard also the mouse and also the hardware clock so what we did last time is we established a connection between the CPU and programmable interrupt controller and we actually you receive the first interrupt from the clock this is a good thing so this means that we actually have a connection now but it's we had a problem that after we got this interrupt the system just stopped and that's not what it is supposed to do you know it's actually supposed to get the next time I interrupt the next time I interrupt and you know we have a problem that we didn't answer the interrupt so we didn't tell the programmable interrupt controller okay done I've I have received this and it's ok you can continue with whatever you were doing before and we will do this in this video now and then we can actually really start to get a decent communication with keyboard ok so the problem that we have now is if this is your C++ world so here we have our kernel main and we built this object with the global descriptor table and interrupt manager and we connect these in our objects in a way and now an interrupt occurs and the interrupt kicks us out of the superclass world into into something like an assembler world right so so that's why we wrote the assembler code which which did all this hard stuff just to get back into the C++ world but so far we only went into the into aesthetic into a static function right so and that's not really what we want right and then I mean we are writing this in C++ because we want to have the power of object orientation so we really want to get back from the static function back into the into this object into this object-oriented construct right so an actually to answer the interrupt to the pic we have to send data back through the command and data ports and yeah but the command pods and data ports they are actually members of this interrupt manager right so these are members of the interrupt managers of we actually have to get from this aesthetic function into a method of the inter manager just to have access to the to the connection to the pick okay and I'm actually not a big fan of this so what we'll do is we will have a static pointer to the interrupt manager I mean I'm not a big fan of having static pointers to two things and but I think really we don't have much of an option right now because we are in a static environment at this point and in a static environment we only have access to the static object so we need to have a pointer to the interrupt manager in a static variable as I said not a really great design but I don't think we have much of an option so so what I'll do now is in here in the interrupt stage I will put a pointer to the current interim manager so we only have we only can have one active interrupt manager so now that we have this and our handle interrupts function will then call the non-static method to handle interrupts of that of that interrupt manager object here okay so in the interrupt of cpp and we need to have I mean this is a static object so we we must put the initialization here initialized with zero and then here in the activate method we will just set this to this point but I mean in theory we could have multiple interrupt line address I mean but that doesn't actually make sense right because the processor has only one one interrupt descriptor table and so there can only one there can be only one active interrupt manager at a time so but I'll put this here if the interrupt manager has already been set then we will deactivate the old one and then set the new one and deactivate so if if we are calling deactivate on on on the active interrupt manager than it is supposed to deactivate it and if we are calling it on in on a different object then it is already inactive so then we don't have to do anything so okay so okay now in the handle interrupt we can now oops we can now use this pointer and how do handle interrupts on it and the blue handle interrupts will basically be the same thing just on an object so uh so we were just has the the parameters and return what we get back from that object and otherwise we addressed return the original PSP okay so now let's have this do handle interrupts methods and so here we put the stuff that we really do now so this should be the same way before okay so what we've seen now is yeah I mean the the operating system does the same thing as before now but but in a different way so what we did now is we jumped from this static function back into the interrupt manager object and there we have access to the to the picker connection okay so yeah what we can do now is at this point in this to handle interrupt method we can now actually we can actually send the answer to the interrupt and then then the program the operating system were not hard here so let's see so in this method okay so we only have to send answers to the hardware interrupts so we have to I mean which other hardware interrupts we have remapped the hardware interrupts from the pic to 0 X 22 0 X 30 so so in this case we have to to send an answer so this is the answer that they pick once and if we are also so so this is the answer for the master pick and maybe we also have to send an answer to the slave but not always so the same answer but only if this was actually a an interrupt that came from the slave so only if the interrupt number has been between zero X 28 and 0 X 30 okay now let's see what happens now and you see now we get lots of interrupts so this is really a good thing so stop this yeah I'm really happy right now so so this works kind of already and I mean we don't want to have this this output every time we get in a timer interrupt right so so I would say that this output should only be there if if we are not if the interrupt is not the timer interrupts and the time I interrupt us to interrupt 20 so so if we run this now then we don't get this output because yeah we still get the interrupt but we don't print them on the screen all the time because they are really not that interesting right so yeah so now we get all the interrupts what do we do next well I mean we are programming this in C++ right so we want to to use object orientation and the object-oriented way of proceeding now would be to to have objects for the different interrupts right so then so for example for interrupts 0 X 21 which was a hard keyboard interrupt we would want something like a keyboard driver or something which handles that interrupts right so so we need to define some interface for for these keyboard drivers Mouse drivers and so on which the interrupt manager can then use okay so what I'll do now is I'll have another base class called interrupt handler and this will so the base class we basically just know it's own interrupts number so and the pointer to the interrupt manager that it is connected to okay and yeah I want to make the the constructor and destructor protected so that you cannot instantiate this you know on we don't have purely virtual functions and so we cannot have abstract classes so I'll just handle it in the way that made by making the constructor protected okay so this should work and we will also make this new class a friend of the interrupt manager okay and now we will have basically something like the interrupt descriptor table but on a higher level so here we will have an area of interrupt handlers like this okay so now we have to implement these these methods okay so the the constructor will just throw other the values you give it and then it will put itself into this into this area of the interrupt manager and in the destructor it will unregister itself okay like this and to standard behavior for handle interrupts is just returning ESP again okay now in the constructor of the interrupt manager we also have to set the handlers to zero like this and then down here we can proceed and say handlers so if we have a handler for it when we when we call its handle interrupts method giving it those decremental okay okay and then we can print this message about an interrupt that we couldn't do anything with only in the Earth's case here so if if we have an interrupt handler then we use that otherwise we print this message so this will also tell us the number of interrupts that we didn't handle okay this looks good okay so some object I wasn't just wasn't updated and so just make clean and make run fix the error so okay so um okay so now the so now the interrupts work as we want them to now the next thing we can do is we can write a driver for the keyboard and because if I mean if we just activate at the keyboard and you press a key then the pic will send the interrupt the CPU will tell the pic okay I'm done with the interrupts the problem is that the kernel would still stop it would not continue running because the pic would not accept the answer from the CPU the reason is if you get a keyboard input then the pic demands that the CPU fetches that input before it tells the pic okay I'm done so so that's what we will do next we will make a driver class for the keyboard it will be derived from from the interrupt handler and it will have its own thoughts and then we were just activated and if the interrupt comes it will read from the data port and then we will have an actual an actual hardware response okay so let's do this okay keep up H the usual stuff okay so this class needs two parts and this is really relatively normal design which we will see very often in the future so we will have just two parts a data port in the command pod wait okay so in this keyboard CTP will have to do a little bit in in the constructor so the interrupt handler is first so the interrupt handlers for to interrupt 0x 21 that's the keyboard interrupt and we just has the miniature object to the base constructor then we construct the data port which is 4 0 X 60 and the command thought which was part zero x64 okay so down here if if we know there is a key strike then we have to fetch it like this and I'll just copy this okay so this will bring the key and we need to have the forward declaration for printf so that it accepts calling printf okay now in the constructor so this when we start communication with the hardware we were just wait for I mean if if you start your operating system and you hold down some key whyever this will just wait for you two to stop pressing that key and it will just remove all the other key strikes that have that might have been there before so this command tells the tells the pig to start sending keyboard interrupts I think or maybe it tells a keyboard to communicate using interrupts and not after that we send it the command 20 which means give us your current state and then we read that then we set the the leftmost bit to one because this will be the new state and we will also clear the fifth bit like this so then we write command 60 which tells the pic or the keyboard to change the current state so you see we set command 0 X 20 which gives us the current state then we change to the current state and write it back so and I think this finally really activates the keyboard oh I almost forgot we need to put this of course also here and in the kernel we have to include the header and instantiate the object and notices we instantiate it between the instantiation of the interrupt manager and the activation of the interrupt manager and it's a pointer to the interrupt manager this okay so this should work now okay it didn't do anything okay so now we have an interrupt from the keyboard 0xf AI think this basically says okay I'm fine with I'm done doing whatever I need to do so I'm ready now I think this is what that means now when when you press keys the first times you saw the first times you press a key you will get this this keyboard key code 0 X 45 + 0 X c5 and I think that's the key code for the num lock and I think this is what VirtualBox does to to tell the virtual machine the state of the num lock so I think we can really ignore them and yeah I think this FA is really a status interim so we could ignore that also so we could put some some some if statements here which say ok for 0 X 45 + 0 X c5 we don't do this in a better way let's say switch the key and this is just the default behavior and for 0x 45 we just do nothing and also for this 0xf a okay now now when you press a key I just pressed the a key and you see we get to interrupts so the first one when I press it and if I keep holding it I get the same interrupts over and over again and when I stop pressing then I get basically the same interrupt but the first other the first bit of this 8-bit integral is just one 4q release and zero four key press okay so so you will get the same key code twice you know one when you press the key and again when you release the key just with with a different first bit so so maybe we'll just ignore keys key codes so yeah so everything everything after 0x80 other the key release interrupts and we are at this point we are not that much interested in it so I press a b c d and you will realize the the key codes that you get they are terrible I told you they are terrible they are all over the place so you will not really happen you will just have to to take a pre sheet of paper and press every single key and see which which key code do you get and write that down and then for every single key you will have to make your own case here and that's really that's really crazy I tell you this so let's see just as an example I'll just put case 0 X 1 and in that case our printf the letter a because it's a key code on this keyboard well the worst thing of this the West part of this is on different keyboards the same key codes will have different meanings so here if I press Z I get 0 X 15 and on American keyboards 0 X 15 is a y and this is stuff that you probably remember from back in the days when when you remember the DOS programming this is stuff you had to deal with back in these days right but so so now I've compiled this again executed it again now I press a and you get an a great isn't it so so now we finally get real data from from the hardware you know if I press a again I get mores and then you what you would do next now is just fill in all the cases with all the other with all the other he bought key codes and yeah maybe you just copy and paste those thing from my zip file but whatever so this is really a bit tedious and I'm not going to put this in this video now so so this this should be enough for today I think we have really achieved something a really a milestone now because now we really get data from the hardware we we press the key the key a and we put an A on the screen and this is really a great feeling I think one thing I want to tell you at this point you at least I when I went when I came to this point for the first time I thought hey this is great I want to run this on the actual hardware and I said make install and rebooted and I pressed the key and nothing happened and that was really frustrating for me and it took me quite a while to figure out what the problem was so the problem was this is a USB connection so on the I mean I mean VirtualBox will communicate with your operating system and pretend there is a pic but on your actual hardware a USB keyboard isn't actually connected to a pig okay I think it is connected to a pig but not like this this would be I think the theists - connections would be directly connected but now you have an actual hardware you will have then you have your mouse there and your keyboards there and with with this scenario you cannot you cannot handle it right now so but my computer at home had luckily it had a BIOS setting I think it was called legacy operating support or something like that and when I enabled this setting the motherboard really did all the USB stuff and then emulated the behavior was the pic and the keyboard and mouse like this and when I enabled this BIOS setting then I could actually press keys and get them on the screen so if you have a setup like this then either you have to stick with with VirtualBox for now or maybe you have such a setting like this in otherwise we you will get to run your stuff on actual Hardware only when when we are at the point where we can communicate with USB okay so this should be enough for today kyun in next time next time we will we will talk about the mouse and but let me tell you now that we have all the stuff with the interrupts and the global descriptor table and everything the mouse is really easy so the mouse is really quite similar to the to the keyboard and and you've seen once we had all the interrupt stuff running we when we we came to the point where we could actually use a keyboard relatively quickly and we'll get to the point where we can use the mouse relatively quickly now also because a really tedious stuff the interrupt descriptor table or the assembler codes the boot manager the boot loader stuff the global descriptor table all this hard stuff is now over we are now finally at a point where we can really do stuff right all this necessary but tedious fundamental stuff is over now and now we can really get going and and do stuff ok so yeah see you next time and don't forget to subscribe so that you don't miss the next video see you next time
Up Next

Building a Keyboard Driver with x86 Interrupts and IDT | OS Development Tutorial
@PageKey
9.2K views•2020-08-12

BitTorrent Protocol Explained: Piece Selection & Peer Choking
@StevenGordonAU
481 views•2013-02-22

HTTP Requests Explained: GET, POST, PUT, DELETE
@codecademy
103.1K views•2021-10-07

Enigma Machine Mechanics: WWII Encryption Explained
@JaredOwen
13.2M views•2021-12-11
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Computer Science














![What are IRQ, DMA & Address Ports? - Soundcard Memories [Byte Size] | Nostalgia Nerd](https://i.ytimg.com/vi_webp/aPKXmGkRxQ8/maxresdefault.webp)
















![[UR] COAL Final Prep Guide, Fall 2024 FAST NUCES LHR](https://i.ytimg.com/vi/cHmH-_l3bF4/sddefault.jpg)





