Index: lab3/Makefile
===================================================================
--- lab3/Makefile	(nonexistent)
+++ lab3/Makefile	(revision 9)
@@ -0,0 +1,16 @@
+# name of the program (Minix service)
+PROG=lab3 
+
+# source code files to be compiled
+SRCS = lab3.c keyboard.c
+
+# additional compilation flags
+# "-Wall -Wextra -Werror -I . -std=c11 -Wno-unused-parameter" are already set
+CFLAGS += -pedantic -DLAB3
+
+# list of library dependencies (for Lab 3, only LCF library)
+DPADD += ${LIBLCF}
+LDADD += -llcf
+
+# include LCOM's makefile that does all the "heavy lifting"
+.include <minix.lcom.mk>
Index: lab3/i8042.h
===================================================================
--- lab3/i8042.h	(nonexistent)
+++ lab3/i8042.h	(revision 9)
@@ -0,0 +1,37 @@
+#ifndef _LCOM_I8042_H_
+#define _LCOM_I8042_H_
+
+#include <lcom/lcf.h>
+
+/** @defgroup i8042 i8042
+ * @{
+ *
+ * Constants for programming the i8042 Keyboard.
+ */
+
+#define KEYBOARD_IRQ 0x09 /* Keyboard IRQ address */
+
+#define BIT(n) (0x01<<(n))
+
+#define DELAY_US        20000
+
+#define STAT_REG_PAR		  BIT(7)  /* Parity Error */
+#define STAT_REG_TIMEOUT	BIT(6)  /* Timeout Error */
+#define STAT_REG_AUX		  BIT(5)  /* Mouse Data */
+#define STAT_REG_INH		  BIT(4)  /* Inhibit Flag */
+#define STAT_REG_A2       BIT(3)  /* A2 Input Line */
+#define STAT_REG_SYS		  BIT(2)  /* System Flag */ 
+#define STAT_REG_IBF	   	BIT(1)  /* Input Buffer Full */
+#define STAT_REG_OBF		  BIT(0)  /* Output Buffer Full */
+
+#define OUTPUT_BUF         0x60    /* Output Buffer */
+#define INPUT_BUF          0x60    /* Input Buffer */
+#define STATUS_REG        0x64    /* Status Register */
+#define KBC_CMD_REG     0x64    /* Command Register */
+#define KBC_CMD_ARG     0x60    /* Command Arguments Adress */
+
+#define ESC_BREAK      0x81
+#define TWO_BYTE_SCANCODE   0xE0  /* Two-byte long scancodes use 0xE0 as their first byte */
+#define MAKE_CODE            BIT(7)
+
+#endif /* _LCOM_I8042_H */
Index: lab3/i8254.h
===================================================================
--- lab3/i8254.h	(nonexistent)
+++ lab3/i8254.h	(revision 9)
@@ -0,0 +1,57 @@
+#ifndef _LCOM_I8254_H_
+#define _LCOM_I8254_H_
+
+#include <lcom/lcf.h>
+
+/** @defgroup i8254 i8254
+ * @{
+ *
+ * Constants for programming the i8254 Timer. Needs to be completed.
+ */
+
+#define TIMER_FREQ 1193182 /**< @brief clock frequency for timer in PC and AT */
+#define TIMER0_IRQ 0 /**< @brief Timer 0 IRQ line */
+
+/* I/O port addresses */
+
+#define TIMER_0    0x40 /**< @brief Timer 0 count register */
+#define TIMER_1    0x41 /**< @brief Timer 1 count register */
+#define TIMER_2    0x42 /**< @brief Timer 2 count register */
+#define TIMER_CTRL 0x43 /**< @brief Control register */
+
+#define SPEAKER_CTRL 0x61 /**< @brief Register for speaker control  */
+
+/* Timer control */
+
+/* Timer selection: bits 7 and 6 */
+
+#define TIMER_SEL0   0x00              /**< @brief Control Word for Timer 0 */
+#define TIMER_SEL1   BIT(6)            /**< @brief Control Word for Timer 1 */
+#define TIMER_SEL2   BIT(7)            /**< @brief Control Word for Timer 2 */
+#define TIMER_RB_CMD (BIT(7) | BIT(6)) /**< @brief Read Back Command */
+
+/* Register selection: bits 5 and 4 */
+
+#define TIMER_LSB     BIT(4)                  /**< @brief Initialize Counter LSB only */
+#define TIMER_MSB     BIT(5)                  /**< @brief Initialize Counter MSB only */
+#define TIMER_LSB_MSB (TIMER_LSB | TIMER_MSB) /**< @brief Initialize LSB first and MSB afterwards */
+
+/* Operating mode: bits 3, 2 and 1 */
+
+#define TIMER_SQR_WAVE (BIT(2) | BIT(1)) /**< @brief Mode 3: square wave generator */
+#define TIMER_RATE_GEN BIT(2)            /**< @brief Mode 2: rate generator */
+
+/* Counting mode: bit 0 */
+
+#define TIMER_BCD 0x01 /**< @brief Count in BCD */
+#define TIMER_BIN 0x00 /**< @brief Count in binary */
+
+/* READ-BACK COMMAND FORMAT */
+
+#define TIMER_RB_COUNT_  BIT(5)
+#define TIMER_RB_STATUS_ BIT(4)
+#define TIMER_RB_SEL(n)  BIT((n) + 1)
+
+/**@}*/
+
+#endif /* _LCOM_I8254_H */
Index: lab3/keyboard.c
===================================================================
--- lab3/keyboard.c	(nonexistent)
+++ lab3/keyboard.c	(revision 9)
@@ -0,0 +1,59 @@
+#include <lcom/lcf.h>
+
+#include <lcom/lab3.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "i8042.h"
+
+
+u8int_t scan_code=0;            // make code or break code
+int keyboard_id = KEYBOARD_IRQ; 	// KEYBOARD_IRQ is defined in interrupt.h in .minix-src folder
+uint32_t cnt = 0;									// counter of sys_inb calls
+					
+int (util_sys_inb)(int port, uint8_t *value) { //transform 8 bit into 32 bit
+
+  uint32_t new_val;                           //initializing 32 bit variable
+
+  if(sys_inb(port,&new_val)!=0){              //verifies if there is an error
+      printf("Error in util_sys_inb\n");
+      return 1;
+  }
+  *value=new_val & 0xFF;                      //dereferencing "value"
+  #ifdef LAB3
+  cnt++;
+  #endif
+  
+
+  return 0;
+}
+
+void (kbc_ih)(void){
+  u8int_t status_reg;
+
+  if(util_sys_inb(STATUS_REG,status_reg)!=0){ //checks if there is an error
+    return;
+  }
+  if(((status_reg & STAT_REG_OBF)==0) ||((status_reg&(STAT_REG_PAR|STAT_REG_TIMEOUT))!=0)){ //checks if there is a parity or timeout error (mask -> 0xC0, bit 7 and 6 set) and checks if output buffer is empty
+    return;
+  }
+  util_sys_inb(OUTPUT_BUF,status_code);
+
+}
+
+int (kbc_subscribe_int)(uint8_t *bit_no) {    //similar function to that of timer_subscribe_int
+    *bit_no = BIT(keyboard_id);
+    if(sys_irqsetpolicy(KEYBOARD_IRQ,(IRQ_REENABLE|IRQ_EXCLUSIVE),&keyboard_id)==1){      //operation to subscribe int
+        printf("Error subscribing int\n");
+        return 1;
+    }
+  return 0;
+}
+
+int (kbc_unsubscribe_int)() {           //similar function to that of timer_unsubscribe_int
+  if(sys_irqrmpolicy(&keyboard_id)==1){
+      printf("Error unsubscribing int\n");
+      return 1;
+  }
+  return 0;
+}
Index: lab3/keyboard.h
===================================================================
--- lab3/keyboard.h	(nonexistent)
+++ lab3/keyboard.h	(revision 9)
@@ -0,0 +1,40 @@
+#include <lcom/lcf.h>
+
+#include <lcom/lab3.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+/**
+* @brief Handles keyboard interrupts (C implementation)
+*
+* Reads the status register and the output buffer (OB).
+* If there was some error, the byte read from the OB should be discarded.
+*
+* All communication with other code must be done via global variables, static if possible.
+*
+* Must be defined using parenthesis around the function name:
+*/
+void (kbc_ih)(void);
+/**
+ * @brief Invokes sys_inb() system call but reads the value into a uint8_t variable.
+ *
+ * @param port the input port that is to be read
+ * @param value address of 8-bit variable to be update with the value read
+ * @return Return 0 upon success and non-zero otherwise
+ */
+int (util_sys_inb)(int port, uint8_t *value);
+/**
+ * @brief Subscribes and enables Keyboard interrupts
+ *
+ * @param bit_no address of memory to be initialized with the
+ *         bit number to be set in the mask returned upon an interrupt
+ * @return Return 0 upon success and non-zero otherwise
+ */
+int(kbc_subscribe_int)(uint8_t *bit_no);
+
+/**
+ * @brief Unsubscribes Keyboard interrupts
+ *
+ * @return Return 0 upon success and non-zero otherwise
+ */
+int(kbc_unsubscribe_int)();
\ No newline at end of file
Index: lab3/lab3.c
===================================================================
--- lab3/lab3.c	(revision 8)
+++ lab3/lab3.c	(revision 9)
@@ -4,7 +4,7 @@
 
 #include <stdbool.h>
 #include <stdint.h>
-
+#include "keyboard.h"
 int main(int argc, char *argv[]) {
   // sets the language of LCF messages (can be either EN-US or PT-PT)
   lcf_set_language("EN-US");
@@ -29,11 +29,64 @@
   return 0;
 }
 
+extern uint8_t scan_reg;
+
 int(kbd_test_scan)() {
-  /* To be completed by the students */
-  printf("%s is not yet implemented!\n", __func__);
+  int r, ipc_status;
+  uint8_t keyboard_irq, size, byte[2]; //size of scancode can be 2 byte long
+  message msg;
+  bool make=false; //to check if code is make or break
 
-  return 1;
+  if(kbc_subscribe_int(keyboard_irq)==1){
+    printf("Error subscribing int\n");
+    return 1;
+  }
+
+  while(scan_code!=ESC_BREAK){      //looping until status_reg is the breakcode of ESC key
+    if ((r = driver_receive(ANY, &msg, &ipc_status))==1){ 
+      printf("driver_receive failed with: %d",r);
+      continue;
+    }
+    if (is_ipc_notify(ipc_status)){                             //received notification
+      switch (_ENDPOINT_P(msg.m_source)){
+        case HARDWARE:                                          //hardware interrupt notification				
+                if (msg.m_notify.interrupts &keyboard_irq){          // subscribed interrupt
+                  
+                  kbc_ih();
+                  bytes[0]=scan_code;
+                  bytes[1]=scan_code;
+
+                  if(bytes[0]==TWO_BYTE_SCANCODE){
+                    size=2;
+                  }
+                  else{
+                    size=1;
+                  }
+
+                  if (scan_code & MAKE_CODE){	// 4 - Checks if code is make or break
+                      make = false;	//break code
+                    }
+                  else {
+                    make = true;  //make code
+                  }
+                  kbd_print_scancode(make, size, bytes); //prints the code
+                      }
+               break;
+        default:
+              break;                                            //no other notifications expected: do nothing	
+        }
+    } 
+    else {                                                      //received a standard message, not a notification
+      //no standard messages expected: do nothing
+    }
+  }
+
+   if (kbc_unsubscribe_int() != 0) { // Check if subscription worked
+		printf("Error unsubscribing int \n");
+		return 1;
+	}
+
+  return 0;
 }
 
 int(kbd_test_poll)() {
