diff --git a/guest/guest.bin b/guest/guest.bin
index 759ecaeecba1bf277b968267be9c0982f1802b7f..3aeb9ac215e6ea70448c7764cd5014a429ca2b56 100755
Binary files a/guest/guest.bin and b/guest/guest.bin differ
diff --git a/guest/guest_main.c b/guest/guest_main.c
index 33bc27de974708b4b1e4f5f11346cb84772ae144..361192161af060a50c832bc73dded1c9c9c4a26a 100644
--- a/guest/guest_main.c
+++ b/guest/guest_main.c
@@ -1,4 +1,5 @@
 #include <stdint.h>
+#include <stdio.h>
 #include "idt.h"
 #include "utils.h"
 #include "pmio.h"
@@ -15,6 +16,8 @@
 #define timer_sleep timer_sleep_phys
 #endif
 
+extern uint32_t key;
+
 void timer_sleep_pv(int usec) {
     hyper_timer_sleep_params_t *timer_sleep_params = (hyper_timer_sleep_params_t*)(SHARED_STORAGE_ADDRESS);
     timer_sleep_params->us = usec;
@@ -66,8 +69,29 @@ void guest_main() {
     // console_pv("Débloquage du display!\n");
     // affichage_pv(400, 300);
 
-    console_pv("Attente de 100000\n");
+    //console_pv("Attente de 100000\n");
     // timer_sleep(10000000);
-    timer_sleep_phys(10000000);
-    console_pv("Après attente!!\n");
+    //timer_sleep_phys(10000000);
+    //console_pv("Après attente!!\n");
+
+    console_pv("Start affichage");
+    affichage_pv(600, 400);
+
+    int quit = 0;
+
+    while (quit == 0)
+    {
+        if (key != 100000){
+            char buffer[100];
+            snprintf(buffer, 100, "Key: %d\n", key);
+            console_pv(buffer);
+            
+            if( key == 27){
+                quit = 1;
+            }
+
+            key = 100000;
+        }
+    }
+    
 }
diff --git a/guest/guest_main.o b/guest/guest_main.o
index cbc944be68e926c84b77b2cf92e4683f2d3acae0..d0161fb98f957fe75efcbfdb35053beac7cb5745 100644
Binary files a/guest/guest_main.o and b/guest/guest_main.o differ
diff --git a/guest/idt.c b/guest/idt.c
index f49386dbe0193b45cff65f8ceca1d39a40f5bc0b..2677ac44e718175652dd7d246bcb41434e6f4a06 100644
--- a/guest/idt.c
+++ b/guest/idt.c
@@ -2,9 +2,14 @@
 #include "utils.h"
 #include "descriptors.h"
 #include "x86.h"
+#include "pmio.h"
 
 #define GDT_KERNEL_CODE_SELECTOR 0x08
 
+// My test
+uint32_t key;
+// --------
+
 // Structure of an IDT descriptor. There are 3 types of descriptors:
 // task-gates, interrupt-gates, trap-gates.
 // See 5.11 of Intel 64 & IA32 architectures software developer's manual for more details.
@@ -53,9 +58,13 @@ static idt_entry_t idt_build_entry(uint16_t selector, uint32_t offset, uint8_t t
 
 // Low level handler defined in idt_asm.s
 void _irq0();
+void _irq1();
 
 // IRQ handler
 void irq_handler(uint32_t irq_number) {
+    if (irq_number == 1){
+        key = ind(0x60);
+    }
 }
 
 void idt_init() {
@@ -66,6 +75,7 @@ void idt_init() {
     memset(idt, 0, sizeof(idt));
 
     idt[0] = idt_build_entry(GDT_KERNEL_CODE_SELECTOR, (uint32_t)_irq0, TYPE_INTERRUPT_GATE, DPL_KERNEL);
+    idt[1] = idt_build_entry(GDT_KERNEL_CODE_SELECTOR, (uint32_t)_irq1, TYPE_INTERRUPT_GATE, DPL_KERNEL);
 
     idt_load(&idt_ptr);
 }
diff --git a/guest/idt.d b/guest/idt.d
index 65b389da664da9d115cfa6614d0f6b42d29e93bf..b6670f00b83433e857f528888cad2cfd8b325bf2 100644
--- a/guest/idt.d
+++ b/guest/idt.d
@@ -1 +1 @@
-idt.o: idt.c idt.h utils.h descriptors.h x86.h
+idt.o: idt.c idt.h utils.h descriptors.h x86.h pmio.h
diff --git a/guest/idt.o b/guest/idt.o
index 43d2c0acb517a821f18afa93c9c2cfe0ab72afb9..49136b163198f4506c134f23c97b4a027fc214c0 100644
Binary files a/guest/idt.o and b/guest/idt.o differ
diff --git a/guest/idt_asm.o b/guest/idt_asm.o
index fcb2a94a593a069eb5c5140768dbe5ef8bbfb6f6..075cc50f013c0946efde3f60635984055d3ac14d 100644
Binary files a/guest/idt_asm.o and b/guest/idt_asm.o differ
diff --git a/guest/idt_asm.s b/guest/idt_asm.s
index bfd31a8b6510d004419aafdac1ca81559c4adb7a..1f0519f1bd80c7b61d1ac7ddd34b329faf97f0e7 100644
--- a/guest/idt_asm.s
+++ b/guest/idt_asm.s
@@ -15,6 +15,11 @@ _irq0:
     push    0  ; put irq number on the stack
     jmp     irq_handler_wrapper
 
+global _irq1
+_irq1:
+    push    1  ; put irq number on the stack
+    jmp     irq_handler_wrapper
+
 extern irq_handler
 
 irq_handler_wrapper:
diff --git a/shared/hypercall_params.h b/shared/hypercall_params.h
index 4dace22345e09541413bb992b007efb45f40c73b..c009169984ad5d6c72e5b3cb03bc924099319a7a 100644
--- a/shared/hypercall_params.h
+++ b/shared/hypercall_params.h
@@ -39,4 +39,8 @@ typedef struct {
     int32_t y ; // y position
 } __attribute__((packed)) hyper_sprite_position_params_t;
 
+typedef struct {
+    uint32_t key ; // code of the pressed key
+} __attribute__((packed)) hyper_keyboard_params_t;
+
 #endif
diff --git a/vmm/peripheriques/disk/disk.c b/vmm/peripheriques/disk/disk.c
index bdba16d5d7433fea8c7cc5d1a036d93afa6cbd97..a3a51fc8d28a931de61cc47bd23876bce204164a 100644
--- a/vmm/peripheriques/disk/disk.c
+++ b/vmm/peripheriques/disk/disk.c
@@ -48,14 +48,14 @@ void disk_store_sector_4(void *addr) {
 }
 
 void disk_store_data(void *addr) {
-    printf("Storring on id=%ld\n", data_index);
+    //printf("Storring on id=%ld\n", data_index);
     buffer_16[data_index] = *(uint16_t *)addr;
     data_index++;
 
     if (data_index == SECTOR_SIZE/2) {
         stop_loop = true;
 
-        printf("Stopping loop after id=%ld\n", data_index);
+        //printf("Stopping loop after id=%ld\n", data_index);
     }
 }
 
@@ -63,7 +63,7 @@ void disk_conclude(void *addr){
 
     hyper_disk_params_t* tmp_params = addr == NULL ? &disk_params : (hyper_disk_params_t*) addr;
     
-    printf("Mem: %d\n", mem);
+    //printf("Mem: %d\n", mem);
 
     // Pv not working for some reason
     // Wrong data writen
@@ -95,5 +95,5 @@ void disk_conclude(void *addr){
     }
 
     fclose(disk);
-    printf("Storing data\n");
+    //printf("Storing data\n");
 }
\ No newline at end of file
diff --git a/vmm/peripheriques/disk/disk.o b/vmm/peripheriques/disk/disk.o
index f85163d96494c7e0bc36af65822977ce741f47f3..a66604d41d53db9c4038ced2b648bfd317b5df8c 100644
Binary files a/vmm/peripheriques/disk/disk.o and b/vmm/peripheriques/disk/disk.o differ
diff --git a/vmm/peripheriques/gfx_init/gfx_init.c b/vmm/peripheriques/gfx_init/gfx_init.c
index afc4a6e5fc4796fa29cea4a71fddc5d6bfd2592c..ced67f4548633c2a73be2f47150dff676a38cb86 100644
--- a/vmm/peripheriques/gfx_init/gfx_init.c
+++ b/vmm/peripheriques/gfx_init/gfx_init.c
@@ -30,7 +30,7 @@ void gfx_init_conclude(void *addr){
     display_width = tmp_params->width;
     display_height = tmp_params->height;
 
-    printf("Initialising display!!! Width: %d, Height: %d\n", display_width, display_height);
+    //printf("Initialising display!!! Width: %d, Height: %d\n", display_width, display_height);
 
     sem_post(&display_sem);
 }
\ No newline at end of file
diff --git a/vmm/peripheriques/gfx_init/gfx_init.o b/vmm/peripheriques/gfx_init/gfx_init.o
index 73bd6e495105bbe4a8bbbd2bc7db3a95f116bbb1..c2a61831039f091a68e922550ab0a62173e3f8ed 100644
Binary files a/vmm/peripheriques/gfx_init/gfx_init.o and b/vmm/peripheriques/gfx_init/gfx_init.o differ
diff --git a/vmm/peripheriques/keyboard/keyboard.c b/vmm/peripheriques/keyboard/keyboard.c
new file mode 100644
index 0000000000000000000000000000000000000000..661d9966459b5e32bfadcb4dac602f861cef01d7
--- /dev/null
+++ b/vmm/peripheriques/keyboard/keyboard.c
@@ -0,0 +1,13 @@
+#include "keyboard.h"
+
+state_t keyboard_states[] = {
+    {WRITE_KEY, 0x60, 0, 4, NULL},
+    {EMULATE, 0, 0, 0, NULL}
+};
+
+state_machine_t keyboard_state_machine = {
+    .current_state = 0,
+    .states = keyboard_states
+};
+
+hyper_keyboard_params_t keyboard_params;
\ No newline at end of file
diff --git a/vmm/peripheriques/keyboard/keyboard.d b/vmm/peripheriques/keyboard/keyboard.d
new file mode 100644
index 0000000000000000000000000000000000000000..b0dee2434a82c6a94eb5b9a667ea43ca34c1bf9e
--- /dev/null
+++ b/vmm/peripheriques/keyboard/keyboard.d
@@ -0,0 +1,4 @@
+peripheriques/keyboard/keyboard.o: peripheriques/keyboard/keyboard.c \
+ peripheriques/keyboard/keyboard.h \
+ peripheriques/keyboard/../state_machine.h \
+ peripheriques/keyboard/../../../shared/hypercall_params.h
diff --git a/vmm/peripheriques/keyboard/keyboard.h b/vmm/peripheriques/keyboard/keyboard.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e0e3aea649443d32c15671df4b1e6512d31a715
--- /dev/null
+++ b/vmm/peripheriques/keyboard/keyboard.h
@@ -0,0 +1,17 @@
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "../state_machine.h"
+#include "../../../shared/hypercall_params.h"
+
+extern state_t keyboard_states[];
+extern state_machine_t keyboard_state_machine;
+extern hyper_keyboard_params_t keyboard_params;
+
+void timer_store(void *addr);
+void timer_conclude(void *addr);
+
+#endif
\ No newline at end of file
diff --git a/vmm/peripheriques/keyboard/keyboard.o b/vmm/peripheriques/keyboard/keyboard.o
new file mode 100644
index 0000000000000000000000000000000000000000..c679dbac3a8d9ca8e5f3203200c200d62756fd74
Binary files /dev/null and b/vmm/peripheriques/keyboard/keyboard.o differ
diff --git a/vmm/peripheriques/peripheriques.c b/vmm/peripheriques/peripheriques.c
index 0e02a86d7daa5f1b2f42bc82dcae3121614b068e..8b24ed0ff651378084a8e28d16837d7e5209c062 100644
--- a/vmm/peripheriques/peripheriques.c
+++ b/vmm/peripheriques/peripheriques.c
@@ -8,25 +8,45 @@ state_machine_t* state_machines[NB_STATE_MACHINE] = {
     &disk_state_machine,
     &sprite_content_state_machine,
     &sprite_visibility_state_machine,
-    &sprite_position_state_machine
+    &sprite_position_state_machine,
+    &keyboard_state_machine
 };
 
 void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){
-    printf("Checking... addr: 0x%lX, size: %d, value: %d\n", addr, size, value);
+    //printf("Checking... addr: 0x%lX, size: %d, value: %d\n", addr, size, value);
     for (int i = 0; i < NB_STATE_MACHINE; i++){
-        printf("State machine n°%d\n", i);
-        printf("State machine state: %d\n", state_machines[i]->current_state);
+        //printf("State machine n°%d\n", i);
+        //printf("State machine state: %d\n", state_machines[i]->current_state);
 
         state_t tmp_state = state_machines[i]->states[state_machines[i]->current_state];
 
         switch (tmp_state.act)
         {
         case WRITE:
-            printf("WRITE\n");
+            //printf("WRITE\n");
             if(tmp_state.address == addr && tmp_state.size == size){
-                printf("Test OK\n");
+                //printf("Test OK\n");
                 *((uint32_t *)addr_p) = (uint32_t)tmp_state.value;
-                printf("Wrote %ld on 0x%lX\n", tmp_state.value, addr);
+                //printf("Wrote %ld on 0x%lX\n", tmp_state.value, addr);
+                state_machines[i]->current_state += 1;
+
+                if(tmp_state.callback != NULL){
+                    tmp_state.callback(addr_p);
+                }
+            }
+            else{
+                state_machines[i]->current_state = 0;
+            }
+            break;
+        case WRITE_KEY:
+            //printf("WRITE_KEY\n");
+            if(tmp_state.address == addr && tmp_state.size == size){
+                printf("Test OK\n");
+                *((uint32_t *)addr_p) = (uint32_t)keyboard_params.key;
+                printf("Wrote %d on 0x%lX\n", keyboard_params.key, addr);
+
+                usleep(100000);
+
                 state_machines[i]->current_state += 1;
 
                 if(tmp_state.callback != NULL){
@@ -38,10 +58,10 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){
             }
             break;
         case STORE:
-            printf("STORE\n");
+            //printf("STORE\n");
 
             if(tmp_state.address == addr && tmp_state.size == size){
-                printf("Test OK\n");
+                //printf("Test OK\n");
                 tmp_state.callback(addr_p);
                 state_machines[i]->current_state += 1;
             }
@@ -50,10 +70,10 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){
             }
             break;
         case STORE_LOOP:
-            printf("STORE_LOOP\n");
+            //printf("STORE_LOOP\n");
 
             if(tmp_state.address == addr && tmp_state.size == size){
-                printf("Test OK\n");
+                //printf("Test OK\n");
                 tmp_state.callback(addr_p);
                 if (stop_loop){
                     state_machines[i]->current_state += 1;
@@ -64,9 +84,9 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){
             }
             break;
         case EQUALS:
-            printf("EQUALS\n");
+            //printf("EQUALS\n");
             if(tmp_state.address == addr && tmp_state.size == size && tmp_state.value == value){
-                printf("Test OK\n");
+                //printf("Test OK\n");
                 state_machines[i]->current_state += 1;
             }
             else{
@@ -77,10 +97,13 @@ void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value){
             break;
         }
 
-        printf("State machine state: %d\n", state_machines[i]->current_state);
+        //cprintf("State machine state: %d\n", state_machines[i]->current_state);
 
         if (state_machines[i]->states[state_machines[i]->current_state].act == EMULATE){
-            state_machines[i]->states[state_machines[i]->current_state].callback(NULL);
+            if(state_machines[i]->states[state_machines[i]->current_state].callback != NULL){
+                state_machines[i]->states[state_machines[i]->current_state].callback(NULL);
+            }
+            
             state_machines[i]->current_state = 0;
         }
     }
diff --git a/vmm/peripheriques/peripheriques.d b/vmm/peripheriques/peripheriques.d
index c4936e7769b80113c8a7167ad14691b5bb2023e9..9695e3233afdb6988511a341601461f68bf16967 100644
--- a/vmm/peripheriques/peripheriques.d
+++ b/vmm/peripheriques/peripheriques.d
@@ -14,4 +14,7 @@ peripheriques/peripheriques.o: peripheriques/peripheriques.c \
  peripheriques/sprites/visibility/sprite_visibility.h \
  peripheriques/sprites/visibility/../sprites.h \
  peripheriques/sprites/position/sprite_position.h \
- peripheriques/sprites/position/../sprites.h
+ peripheriques/sprites/position/../sprites.h \
+ peripheriques/keyboard/keyboard.h \
+ peripheriques/keyboard/../state_machine.h \
+ peripheriques/keyboard/../../../shared/hypercall_params.h
diff --git a/vmm/peripheriques/peripheriques.h b/vmm/peripheriques/peripheriques.h
index 6aadffaee0faa6f6bf0ff2c9c466818a427defeb..afdc737a5f347afc5e6a31aa2d68ab169b239105 100644
--- a/vmm/peripheriques/peripheriques.h
+++ b/vmm/peripheriques/peripheriques.h
@@ -10,8 +10,9 @@
 #include "sprites/content/sprite_content.h"
 #include "sprites/visibility/sprite_visibility.h"
 #include "sprites/position/sprite_position.h"
+#include "keyboard/keyboard.h"
 
-#define NB_STATE_MACHINE 6
+#define NB_STATE_MACHINE 7
 
 void check_state(uint64_t addr, uint8_t* addr_p, uint8_t size, uint32_t value);
 
diff --git a/vmm/peripheriques/peripheriques.o b/vmm/peripheriques/peripheriques.o
index 9ca211e7e4f8933ade41de2a099d26236cb756f3..b045dc7a1c7766b669542cf895b2918bdb76a653 100644
Binary files a/vmm/peripheriques/peripheriques.o and b/vmm/peripheriques/peripheriques.o differ
diff --git a/vmm/peripheriques/sprites/content/sprite_content.c b/vmm/peripheriques/sprites/content/sprite_content.c
index a06e216460b1804f23235f9d33805038b88dceba..c0af4624543065c0c037834a2f55acb494899235 100644
--- a/vmm/peripheriques/sprites/content/sprite_content.c
+++ b/vmm/peripheriques/sprites/content/sprite_content.c
@@ -55,7 +55,5 @@ void sprite_content_store_data(void *addr){
 void sprite_content_conclude(void *addr){
 
 
-    printf("Showing sprite SLOT: %d, WIDTH: %d, HEIGHT: %d\n", sprite_content_params.slot, sprite_content_params.width, sprite_content_params.height);
-
-    usleep(10000000);
+    //printf("Showing sprite SLOT: %d, WIDTH: %d, HEIGHT: %d\n", sprite_content_params.slot, sprite_content_params.width, sprite_content_params.height);
 }
\ No newline at end of file
diff --git a/vmm/peripheriques/sprites/content/sprite_content.o b/vmm/peripheriques/sprites/content/sprite_content.o
index e9e2e02761a9eb7a82a11bd22ef6f425f3c630d9..801b11bc51fe37d49bee9156f6a780495c4072f7 100644
Binary files a/vmm/peripheriques/sprites/content/sprite_content.o and b/vmm/peripheriques/sprites/content/sprite_content.o differ
diff --git a/vmm/peripheriques/sprites/position/sprite_position.c b/vmm/peripheriques/sprites/position/sprite_position.c
index 006319cecf1b5c1e090c0565eaada16dc43fcf75..c26f79905a7ac8fe4c271486a98d32bc7f3d5f8c 100644
--- a/vmm/peripheriques/sprites/position/sprite_position.c
+++ b/vmm/peripheriques/sprites/position/sprite_position.c
@@ -29,7 +29,5 @@ void sprite_position_store_y(void *addr){
 }
 
 void sprite_position_conclude(void *addr){
-    printf("Showing sprite SLOT: %d, X: %d, Y: %d\n", sprite_position_params.slot, sprite_position_params.x, sprite_position_params.y);
-
-    usleep(10000000);
+    //printf("Showing sprite SLOT: %d, X: %d, Y: %d\n", sprite_position_params.slot, sprite_position_params.x, sprite_position_params.y);
 }
\ No newline at end of file
diff --git a/vmm/peripheriques/sprites/position/sprite_position.o b/vmm/peripheriques/sprites/position/sprite_position.o
index f1ee2bb632834dd7f877f619cae4c6eac68171de..9da0a592db38edc142945ab2c8ca888d4ab3b155 100644
Binary files a/vmm/peripheriques/sprites/position/sprite_position.o and b/vmm/peripheriques/sprites/position/sprite_position.o differ
diff --git a/vmm/peripheriques/sprites/visibility/sprite_visibility.c b/vmm/peripheriques/sprites/visibility/sprite_visibility.c
index 896bdabdc6561469cd37e6c73c70a21fffb2628c..90e20cd64cf31d8350620c51dee9697be02b43fa 100644
--- a/vmm/peripheriques/sprites/visibility/sprite_visibility.c
+++ b/vmm/peripheriques/sprites/visibility/sprite_visibility.c
@@ -24,7 +24,5 @@ void sprite_visibility_store_toggle(void *addr){
 }
 
 void sprite_visibility_conclude(void *addr){
-    printf("Showing sprite SLOT: %d, VISIBILITY: %d\n", sprite_visibility_params.slot, sprite_visibility_params.toggle);
-
-    usleep(10000000);
+    //printf("Showing sprite SLOT: %d, VISIBILITY: %d\n", sprite_visibility_params.slot, sprite_visibility_params.toggle);
 }
\ No newline at end of file
diff --git a/vmm/peripheriques/sprites/visibility/sprite_visibility.o b/vmm/peripheriques/sprites/visibility/sprite_visibility.o
index 4105482dbfb26854589a9df0d65c21e8f5db8f21..f5ec981653ac8bc6357b95cecb080f09f42f3c85 100644
Binary files a/vmm/peripheriques/sprites/visibility/sprite_visibility.o and b/vmm/peripheriques/sprites/visibility/sprite_visibility.o differ
diff --git a/vmm/peripheriques/state_machine.h b/vmm/peripheriques/state_machine.h
index 11c0fd6d1fa7801f99431ca46c5a7ecbf3b75892..4d4d7c61c5d7684187c09a4d3ed430e6679913e3 100644
--- a/vmm/peripheriques/state_machine.h
+++ b/vmm/peripheriques/state_machine.h
@@ -7,6 +7,7 @@
 typedef enum t_action_t
 {
     WRITE,
+    WRITE_KEY,
     STORE,
     STORE_LOOP,
     EQUALS,
diff --git a/vmm/peripheriques/timer/timer.c b/vmm/peripheriques/timer/timer.c
index fcc89782d09da30a86692a1cdaa08e20a8c9802c..180c37053065817369270dd147787dfde47fe30b 100644
--- a/vmm/peripheriques/timer/timer.c
+++ b/vmm/peripheriques/timer/timer.c
@@ -20,6 +20,6 @@ void timer_store(void *addr){
 void timer_conclude(void *addr){
     hyper_timer_sleep_params_t* tmp_params = addr == NULL ? &timer_params : (hyper_timer_sleep_params_t*) addr;
 
-    printf("\nTime: %d\n", tmp_params->us);
+    // printf("\nTime: %d\n", tmp_params->us);
     usleep(tmp_params->us);
 }
\ No newline at end of file
diff --git a/vmm/peripheriques/timer/timer.o b/vmm/peripheriques/timer/timer.o
index 84284c1e7d0cdeab224af08a1a65de8800d67c67..c998ddc48f6a3977b0dd715af3d190061ca4a6fc 100644
Binary files a/vmm/peripheriques/timer/timer.o and b/vmm/peripheriques/timer/timer.o differ
diff --git a/vmm/vmm b/vmm/vmm
index 97e079146cc757008d6e95c24a2090587129cae2..e8276973c100f06f69b8301a73bf605f2f5b4172 100755
Binary files a/vmm/vmm and b/vmm/vmm differ
diff --git a/vmm/vmm.c b/vmm/vmm.c
index 6ba03fc7d7bbf571e40be8b73019a14ee6d66bfe..a74227c2ae98878fb77f4fa54c87a8257e51ab17 100644
--- a/vmm/vmm.c
+++ b/vmm/vmm.c
@@ -20,30 +20,36 @@
 
 #define SECTOR_SIZE 512
 
-typedef struct t_guest_os_t {
-    uint8_t* code;
+typedef struct t_guest_os_t
+{
+    uint8_t *code;
     long codeSize;
 } guest_os_t;
 
-guest_os_t* readByteCode(char* filePath){
+guest_os_t *readByteCode(char *filePath)
+{
     FILE *file = fopen(filePath, "rb");
-    if (file == NULL) {
+    if (file == NULL)
+    {
         err(1, "fopen");
     }
 
-    guest_os_t* guest_os = malloc(sizeof(guest_os_t));
+    guest_os_t *guest_os = malloc(sizeof(guest_os_t));
 
     fseek(file, 0, SEEK_END);
     guest_os->codeSize = ftell(file);
     fseek(file, 0, SEEK_SET);
 
     guest_os->code = malloc(guest_os->codeSize);
-    
-    fread(guest_os->code, 1, guest_os->codeSize, file); 
 
-    if (ferror(file)) {
+    fread(guest_os->code, 1, guest_os->codeSize, file);
+
+    if (ferror(file))
+    {
         err(1, "Error reading file.");
-    } else {
+    }
+    else
+    {
         printf("File read successfully.\n");
     }
 
@@ -52,13 +58,16 @@ guest_os_t* readByteCode(char* filePath){
     return guest_os;
 }
 
-void write_sector(uint32_t sector_number, const uint8_t *data) {
-    if (sector_number > MAX_SECTOR_NUM) {
+void write_sector(uint32_t sector_number, const uint8_t *data)
+{
+    if (sector_number > MAX_SECTOR_NUM)
+    {
         fprintf(stderr, "Sector number out of range\n");
     }
-    
+
     FILE *disk = fopen(disk_filename, "r+b");
-    if (!disk) {
+    if (!disk)
+    {
         perror("Failed to open disk file");
     }
 
@@ -66,14 +75,16 @@ void write_sector(uint32_t sector_number, const uint8_t *data) {
     uint64_t offset = (uint64_t)sector_number * SECTOR_SIZE;
 
     // Seek to the sector position
-    if (fseek(disk, offset, SEEK_SET) != 0) {
+    if (fseek(disk, offset, SEEK_SET) != 0)
+    {
         perror("Seek failed");
         fclose(disk);
     }
 
     // Write 512 bytes to the specified sector
     size_t bytes_written = fwrite(data, 1, SECTOR_SIZE, disk);
-    if (bytes_written != SECTOR_SIZE) {
+    if (bytes_written != SECTOR_SIZE)
+    {
         perror("Failed to write full sector");
         fclose(disk);
     }
@@ -90,47 +101,55 @@ sem_t display_sem;
 
 uint32_t display_width, display_height;
 
-static uint32_t read_data(uint8_t *addr, uint8_t size) {
+static uint32_t read_data(uint8_t *addr, uint8_t size)
+{
     uint32_t value;
 
-    switch (size) {
-        case 1:
-            value = *(uint8_t *)addr;
+    switch (size)
+    {
+    case 1:
+        value = *(uint8_t *)addr;
         break;
-        case 2:
-            value = *(uint16_t *)addr;
+    case 2:
+        value = *(uint16_t *)addr;
         break;
-        case 4:
-            value = *(uint32_t *)addr;
+    case 4:
+        value = *(uint32_t *)addr;
         break;
-        default:
-            errx(1, "Unsupported size trying to retrieve data.\n");
+    default:
+        errx(1, "Unsupported size trying to retrieve data.\n");
         break;
     }
 
     return value;
 }
 
-void* vcpu_thread_func(void* args){
-    while (1) {
-        if (ioctl(vcpufd, KVM_RUN, NULL) == -1){
+void *vcpu_thread_func(void *args)
+{
+    while (1)
+    {
+        if (ioctl(vcpufd, KVM_RUN, NULL) == -1)
+        {
             err(1, "KVM_RUN");
         }
-            
-        switch (run->exit_reason) {
+
+        switch (run->exit_reason)
+        {
         case KVM_EXIT_HLT:
             puts("KVM_EXIT_HLT");
             return 0;
         case KVM_EXIT_IO:
-            printf("KVM_EXIT_IO\n");
-            if (run->io.direction == KVM_EXIT_IO_OUT){
-                uint32_t value = read_data((uint8_t*) run + run->io.data_offset, run->io.size);
-                if(run->io.size == 1 && run->io.port == 0xABBA){
-                    printf("HYPERCALL!!\n");
+            // printf("KVM_EXIT_IO\n");
+            if (run->io.direction == KVM_EXIT_IO_OUT)
+            {
+                uint32_t value = read_data((uint8_t *)run + run->io.data_offset, run->io.size);
+                if (run->io.size == 1 && run->io.port == 0xABBA)
+                {
+                    // printf("HYPERCALL!!\n");
                     switch (value)
                     {
                     case 1:
-                        hyper_console_params_t console_params = *(hyper_console_params_t*)shared_mem;
+                        hyper_console_params_t console_params = *(hyper_console_params_t *)shared_mem;
                         printf("%s", (char *)mem + console_params.msg);
                         break;
                     case 2:
@@ -151,10 +170,10 @@ void* vcpu_thread_func(void* args){
                         gfx_init_conclude(shared_mem);
                         break;
                     case 4:
-                        hyper_disk_params_t disk_params = *(hyper_disk_params_t*)shared_mem;
-                        uint8_t *data_addr = (uint8_t*) mem + disk_params.data;
+                        hyper_disk_params_t disk_params = *(hyper_disk_params_t *)shared_mem;
+                        uint8_t *data_addr = (uint8_t *)mem + disk_params.data;
                         write_sector(disk_params.sector_idx, data_addr);
-                        
+
                         disk_conclude(shared_mem);
                         break;
                     case 5:
@@ -167,22 +186,26 @@ void* vcpu_thread_func(void* args){
                         break;
                     }
                 }
-                else{
-                    check_state(run->io.port, (uint8_t*) run + run->io.data_offset, run->io.size, value);
+                else
+                {
+                    check_state(run->io.port, (uint8_t *)run + run->io.data_offset, run->io.size, value);
                 }
             }
-            else if (run->io.direction == KVM_EXIT_IO_IN) {
-                check_state(run->io.port, (uint8_t*) run + run->io.data_offset, run->io.size, 0);
+            else if (run->io.direction == KVM_EXIT_IO_IN)
+            {
+                check_state(run->io.port, (uint8_t *)run + run->io.data_offset, run->io.size, 0);
             }
 
             break;
         case KVM_EXIT_MMIO:
-            printf("KVM_EXIT_MMIO\n");
-            if (run->mmio.is_write) {
+            // printf("KVM_EXIT_MMIO\n");
+            if (run->mmio.is_write)
+            {
                 uint32_t value = read_data((uint8_t *)run->mmio.data, run->mmio.len);
                 check_state(run->mmio.phys_addr, run->mmio.data, run->mmio.len, value);
             }
-            else if (!run->mmio.is_write) {
+            else if (!run->mmio.is_write)
+            {
                 check_state(run->mmio.phys_addr, run->mmio.data, run->mmio.len, 0);
             }
             break;
@@ -197,100 +220,135 @@ void* vcpu_thread_func(void* args){
     }
 }
 
-int main(int argc, char **argv){
+int main(int argc, char **argv)
+{
 
-    guest_os_t* guest_os = readByteCode(argv[1]);
+    guest_os_t *guest_os = readByteCode(argv[1]);
     disk_filename = argv[2];
     printf("Disk filename: %s\n", disk_filename);
 
     int kvmfd = open("/dev/kvm", O_RDWR | O_CLOEXEC);
-    if(kvmfd == -1){
+    if (kvmfd == -1)
+    {
         err(1, "/dev/kvm");
     }
 
     int version = ioctl(kvmfd, KVM_GET_API_VERSION, NULL);
-    if(version == -1){
-        err (1 , "KVM_GET_API_VERSION") ;
-    }   
-    if(version != KVM_API_VERSION){
+    if (version == -1)
+    {
+        err(1, "KVM_GET_API_VERSION");
+    }
+    if (version != KVM_API_VERSION)
+    {
         err(1, "Unsupported version of the KVM API");
     }
 
     int vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
-    if(vmfd == -1){
-        err(1, "KVM_CREATE_VM");        
+    if (vmfd == -1)
+    {
+        err(1, "KVM_CREATE_VM");
     }
 
     uint64_t ram_size = 512 * 4096;
-    mem = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0) ;
-    if(!mem){
+    mem = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (!mem)
+    {
         err(1, "Allocating guest memory");
     }
 
     printf("Size: %ld\n", guest_os->codeSize);
     memcpy(mem, guest_os->code, guest_os->codeSize);
 
-    struct kvm_userspace_memory_region memreg = {   
+    struct kvm_userspace_memory_region memreg = {
         .slot = 0,
         .guest_phys_addr = 0,
         .memory_size = ram_size,
         .userspace_addr = (uint64_t)mem,
-        .flags = 0
-    };
-    if(ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) == -1){
-        err(1 , "KVM_SET_USER_MEMORY_REGION");
+        .flags = 0};
+    if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg) == -1)
+    {
+        err(1, "KVM_SET_USER_MEMORY_REGION");
     }
 
     uint64_t shared_size = 4096;
-    shared_mem = mmap(NULL, shared_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0) ;
-    if(!shared_mem  ){
+    shared_mem = mmap(NULL, shared_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (!shared_mem)
+    {
         err(1, "Allocating guest memory");
     }
 
-    struct kvm_userspace_memory_region shared_memreg = {   
-        .slot = 1   ,
+    struct kvm_userspace_memory_region shared_memreg = {
+        .slot = 1,
         .guest_phys_addr = 3ULL * 1024 * 1024 * 1024,
         .memory_size = shared_size,
-        .userspace_addr = (uint64_t)shared_mem, 
-        .flags = 0
+        .userspace_addr = (uint64_t)shared_mem,
+        .flags = 0};
+    if (ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &shared_memreg) == -1)
+    {
+        err(1, "KVM_SET_USER_MEMORY_REGION 2");
+    }
+
+    if (ioctl(vmfd, KVM_CREATE_IRQCHIP, NULL) < 0)
+    {
+        err(1, "KVM_GET_IRQCHIP");
+    }
+
+    struct kvm_irqchip irqchip = {
+        .chip_id = 0, // 0 = PIC1 , 1 = PIC2 , 2 = IOAPIC
     };
-    if(ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &shared_memreg) == -1){
-        err(1 , "KVM_SET_USER_MEMORY_REGION 2");
+
+    // Retrieve the PIC registers
+    if (ioctl(vmfd, KVM_GET_IRQCHIP, &irqchip) < 0)
+    {
+        err(1, "KVM_GET_IRQCHIP 1");
+    }
+
+    irqchip.chip.pic.auto_eoi = 1;
+
+    if (ioctl(vmfd, KVM_SET_IRQCHIP, &irqchip) < 0)
+    {
+        err(1, "KVM_SET_IRQCHIP 2");
     }
 
     vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
-    if(vcpufd < 0){
+    if (vcpufd < 0)
+    {
         err(1, "KVM_CREATE_VCPU");
     }
 
     int vcpu_mmap_sz = ioctl(kvmfd, KVM_GET_VCPU_MMAP_SIZE, NULL);
-    if(vcpu_mmap_sz == -1){
+    if (vcpu_mmap_sz == -1)
+    {
         err(1, "KVM_GET_VCPU_MMAP_SIZE");
     }
-    if(vcpu_mmap_sz < sizeof(struct kvm_run)){
+    if (vcpu_mmap_sz < sizeof(struct kvm_run))
+    {
         err(1, "KVM_GET_VCPU_MMAP_SIZE unexpectedly small");
     }
 
     run = mmap(NULL, vcpu_mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0);
-    if(!run){
+    if (!run)
+    {
         err(1, "mmap vcpu");
     }
 
-    struct kvm_sregs sregs ;
-    if(ioctl(vcpufd, KVM_GET_SREGS, &sregs) == -1){
+    struct kvm_sregs sregs;
+    if (ioctl(vcpufd, KVM_GET_SREGS, &sregs) == -1)
+    {
         err(1, "KVM_GET_SREGS");
     }
 
     sregs.cs.base = 0;
     sregs.cs.selector = 0;
-    sregs.ds.base = 0;  
+    sregs.ds.base = 0;
     sregs.ds.selector = 0;
     sregs.es.base = 0;
     sregs.es.selector = 0;
     sregs.ss.base = 0;
     sregs.ss.selector = 0;
 
-    if(ioctl(vcpufd, KVM_SET_SREGS, &sregs) == -1){
+    if (ioctl(vcpufd, KVM_SET_SREGS, &sregs) == -1)
+    {
         err(1, "KVM_SET_SREGS");
     }
 
@@ -300,8 +358,9 @@ int main(int argc, char **argv){
     regs.rip = 0;
     regs.rsp = ram_size;
     regs.rflags = 0x2;
-    
-    if(ioctl(vcpufd, KVM_SET_REGS, &regs) == -1){
+
+    if (ioctl(vcpufd, KVM_SET_REGS, &regs) == -1)
+    {
         err(1, "KVM_SET_REGS");
     }
 
@@ -317,7 +376,46 @@ int main(int argc, char **argv){
 
     gfx_context_t *ctxt = gfx_create("Display", display_width, display_height);
 
-    if(pthread_join(vcpu_thread, NULL)==-1){
+    bool quit = false;
+
+    while (!quit)
+    {
+        SDL_Keycode key = gfx_keypressed();
+
+        if (key != 0)
+        {
+            keyboard_params.key = key;
+
+            struct kvm_irq_level irq_level;
+            irq_level.irq = 1;
+
+            irq_level.level = 1;
+            if (ioctl(vmfd, KVM_IRQ_LINE, &irq_level) < 0)
+            {
+                err(1, "KVM_GET_IRQCHIP UP");
+            }
+
+            irq_level.level = 0;
+            if (ioctl(vmfd, KVM_IRQ_LINE, &irq_level) < 0)
+            {
+                err(1, "KVM_GET_IRQCHIP DOWN");
+            }
+
+            printf("Stored Key: %d\n", keyboard_params.key);
+            // sleep(10);
+            // usleep(10000000);
+
+            if (key == SDLK_ESCAPE)
+            {
+                quit = true;
+            }
+        }
+    }
+
+    pthread_cancel(vcpu_thread);
+
+    if (pthread_join(vcpu_thread, NULL) == -1)
+    {
         err(1, "pthread_join");
     }
     gfx_destroy(ctxt);
diff --git a/vmm/vmm.d b/vmm/vmm.d
index 9aaecd3e45d7712578fad8e38507269287475b27..39fc2c3bcc7287dfec18ed13ce9870267b7dfac9 100644
--- a/vmm/vmm.d
+++ b/vmm/vmm.d
@@ -14,4 +14,7 @@ vmm.o: vmm.c ../shared/hypercall_params.h gfx/gfx.h \
  peripheriques/sprites/visibility/sprite_visibility.h \
  peripheriques/sprites/visibility/../sprites.h \
  peripheriques/sprites/position/sprite_position.h \
- peripheriques/sprites/position/../sprites.h
+ peripheriques/sprites/position/../sprites.h \
+ peripheriques/keyboard/keyboard.h \
+ peripheriques/keyboard/../state_machine.h \
+ peripheriques/keyboard/../../../shared/hypercall_params.h
diff --git a/vmm/vmm.o b/vmm/vmm.o
index 4c48b43b41dd8dc4eb5610e5d1083e00fac67519..778c71c6720e4ea5ca446543501f6e961982c3bf 100644
Binary files a/vmm/vmm.o and b/vmm/vmm.o differ