Index: proj/Makefile
===================================================================
--- proj/Makefile	(revision 144)
+++ proj/Makefile	(revision 145)
@@ -1,6 +1,6 @@
 PROG=proj
 
-SRCS= proj.c utils.c
+SRCS= proj.c
 
 CPPFLAGS += -pedantic -D __LCOM_OPTIMIZED_
 
Index: proj/errors.h
===================================================================
--- proj/errors.h	(revision 144)
+++ proj/errors.h	(revision 145)
@@ -1,6 +1,7 @@
 #ifndef ERRORS_H_INCLUDED
 #define ERRORS_H_INCLUDED
 
+/** @brief Error Codes */
 enum errors {
     SUCCESS = 0,        /* @brief Sucessful */
     NULL_PTR,           /* @brief Null Pointer Error */
Index: proj/kbc.c
===================================================================
--- proj/kbc.c	(nonexistent)
+++ proj/kbc.c	(revision 145)
@@ -0,0 +1,74 @@
+#include <lcom/lcf.h>
+
+#include "kbc.h"
+
+#include "kbc_macros.h"
+#include "utils.h"
+#include "errors.h"
+
+int (kbc_read_cmd)(uint8_t *cmd){
+    int ret = 0;
+    if((ret = kbc_issue_cmd(READ_KBC_CMD))) return ret;
+    if((ret = kbc_read_byte(cmd))) return ret;
+    return SUCCESS;
+}
+
+int (kbc_change_cmd)(uint8_t cmd){
+    int ret = 0;
+    if((ret = kbc_issue_cmd(WRITE_KBC_CMD))) return ret;
+    if((ret = kbc_issue_arg(cmd))) return ret;
+    return SUCCESS;
+}
+
+int (kbc_restore_kbd)(){
+    int ret = 0;
+    uint8_t cmd = 0;
+    if((ret = kbc_read_cmd(&cmd))) return ret;
+    cmd = (cmd | INT_KBD) & (~DIS_KBD);
+    if((ret = kbc_change_cmd(cmd))) return ret;
+    return SUCCESS;
+}
+
+int (kbc_issue_cmd)(uint8_t cmd){
+    int ret = 0;
+    uint8_t stat;
+    for(int i = 0; i < KBC_NUM_TRIES; ++i){
+        if((ret = util_sys_inb(STATUS_REG, &stat))) return ret;
+        if((stat&IN_BUF_FULL) == 0){
+            if(sys_outb(KBC_CMD, cmd)) return WRITE_ERROR;
+            return SUCCESS;
+        }
+        tickdelay(micros_to_ticks(DELAY));
+    }
+    return TIMEOUT_ERROR;
+}
+
+int (kbc_issue_arg)(uint8_t arg){
+    int ret = 0;
+    uint8_t stat;
+    for(int i = 0; i < KBC_NUM_TRIES; ++i){
+        if((ret = util_sys_inb(STATUS_REG, &stat))) return ret;
+        if((stat&IN_BUF_FULL) == 0){
+            if(sys_outb(KBC_CMD_ARG, arg)) return WRITE_ERROR;
+            return SUCCESS;
+        }
+        tickdelay(micros_to_ticks(DELAY));
+    }
+    return TIMEOUT_ERROR;
+}
+
+int (kbc_read_byte)(uint8_t *byte){
+    int ret = 0;
+    uint8_t stat;
+    for(int i = 0; i < KBC_NUM_TRIES; ++i){
+        if((ret = util_sys_inb(STATUS_REG, &stat))) return ret;
+        if((stat&OUT_BUF_FUL) && (stat&AUX_MOUSE)==0){
+            if(stat & (PARITY_ERROR | TIME_OUT_REC)) return OTHER_ERROR;
+            if((ret = util_sys_inb(OUTPUT_BUF, byte))) return ret;
+            else return SUCCESS;
+        }
+        tickdelay(micros_to_ticks(DELAY));
+    }
+    printf("Timing out\n");
+    return TIMEOUT_ERROR;
+}

Property changes on: proj/kbc.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/kbc.h
===================================================================
--- proj/kbc.h	(nonexistent)
+++ proj/kbc.h	(revision 145)
@@ -0,0 +1,55 @@
+/**
+ * This file concerns everything related to the KBC (KeyBoard Controller, which
+ * actually also manages the mouse)
+ */
+
+#ifndef KBC_H_INCLUDED
+#define KBC_H_INCLUDED
+
+/**
+ * @brief High-level function that reads the command byte of the KBC
+ * @param cmd Pointer to variable where command byte read from KBC will be stored
+ * @return 0 if operation was successful, 1 otherwise
+ */
+int (kbc_read_cmd)(uint8_t *cmd);
+
+/**
+ * @brief High-level function that changes the command byte of the KBC
+ * @param cmd New value for command byte of KBC
+ * @return 0 if operation was successful, 1 otherwise
+ */
+int (kbc_change_cmd)(uint8_t cmd);
+
+/**
+ * @brief High-level function that restores KBC to normal state
+ * High-level function that restores KBC to normal state, because lcf_start
+ * changes the command byte of KBC. If this function is not used, there is a
+ * chance that the keyboard and keyboard interrupts remain disabled.
+ * @return 0 if operation was successful, 1 otherwise
+ */
+int (kbc_restore_keyboard)();
+
+/**
+ * @brief Low-level function to issue a command to keyboard
+ * @param cmd command to be issued
+ * @return 0 if operation was successful, 1 otherwise
+ */
+int (kbc_issue_cmd)(uint8_t cmd);
+
+/**
+ * @brief Low-level function to issue an argument of a command
+ * @param cmd argument to be issued
+ * @return 0 if operation was successful, 1 otherwise
+ */
+int (kbc_issue_arg)(uint8_t arg);
+
+/**
+ * @brief Low-level function for reading byte from keyboard
+ * Low-level function for reading byte from keyboard. Waits until output buffer
+ * is full
+ * @param value Pointer to variable where byte read from keyboard will be stored
+ * @return 0 if operation was successful, 1 otherwise
+ */
+int (kbc_read_byte)(uint8_t *byte);
+
+#endif //KBC_H_INCLUDED

Property changes on: proj/kbc.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/keyboard.c
===================================================================
--- proj/keyboard.c	(nonexistent)
+++ proj/keyboard.c	(revision 145)
@@ -0,0 +1,57 @@
+#include <lcom/lcf.h>
+
+#include "keyboard.h"
+
+#include "kbc.h"
+#include "kbc_macros.h"
+#include "utils.h"
+#include "errors.h"
+
+int (subscribe_kbc_interrupt)(uint8_t interrupt_bit, int *interrupt_id) {
+    if (interrupt_id == NULL) return NULL_PTR;
+    *interrupt_id = interrupt_bit;
+    if(sys_irqsetpolicy(KBC_IRQ, IRQ_REENABLE | IRQ_EXCLUSIVE, interrupt_id)) return SBCR_ERROR;
+    return SUCCESS;
+}
+
+int done = 1;
+int sz = 1;
+int got_error_keyboard = SUCCESS;
+
+void (kbc_ih)(void) {
+    if(done) sz = 1;
+    else     sz++;
+    uint8_t status = 0;
+    got_error_keyboard = SUCCESS;
+    if ((got_error_keyboard = util_sys_inb(STATUS_REG, &status))) return;
+    if (status & (TIME_OUT_REC | PARITY_ERROR)) {
+        got_error_keyboard = 1;
+        return;
+    }
+    if ((status & OUT_BUF_FUL) == 0 || (status & AUX_MOUSE) != 0) {
+        got_error_keyboard = READ_ERROR;
+        return;
+    }
+    uint8_t byte = 0;
+    if ((got_error_keyboard = util_sys_inb(OUTPUT_BUF, &byte))) return;
+
+    scancode[sz-1] = byte;
+    done = !(TWO_BYTE_CODE == byte);
+}
+
+int (keyboard_poll)(uint8_t bytes[], uint8_t *size){
+    int ret = 0;
+    if(bytes == NULL || size == NULL) return NULL_PTR;
+    uint8_t c;
+    if((ret = kbc_read_byte(&c))) return ret;
+    if(c == TWO_BYTE_CODE){
+        if((ret = kbc_read_byte(&bytes[1]))) return ret;
+        bytes[0] = c;
+        *size = 2;
+    }else{
+        bytes[1] = 0;
+        bytes[0] = c;
+        *size = 1;
+    }
+    return SUCCESS;
+}

Property changes on: proj/keyboard.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/keyboard.h
===================================================================
--- proj/keyboard.h	(nonexistent)
+++ proj/keyboard.h	(revision 145)
@@ -0,0 +1,19 @@
+/**
+ * This file concerns everything related to the keyboard
+ */
+
+#ifndef KEYBOARD_H_INCLUDED
+#define KEYBOARD_H_INCLUDED
+
+int (subscribe_kbc_interrupt)(uint8_t interrupt_bit, int *interrupt_id);
+
+uint8_t scancode[2];
+int done;
+int sz;
+int got_error_keyboard;
+
+void (kbc_ih)(void);
+
+int (keyboard_poll)(uint8_t bytes[], uint8_t *size);
+
+#endif //KEYBOARD_H_INCLUDED

Property changes on: proj/keyboard.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/utils.c
===================================================================
--- proj/utils.c	(revision 144)
+++ proj/utils.c	(revision 145)
@@ -17,10 +17,6 @@
     return SUCCESS;
 }
 
-#ifdef LAB3
-    uint32_t sys_inb_counter = 0;
-#endif
-
 int (util_sys_inb)(int port, uint8_t *value) {
     if(value == NULL) return NULL_PTR;
     uint32_t n = 0;
@@ -29,8 +25,10 @@
     return SUCCESS;
 }
 
-int16_t abs16(int16_t x) {
-    return (x >= 0) ? (int16_t)(x) : (int16_t)(-x);
+int (unsubscribe_interrupt)(int *interrupt_id) {
+    if (interrupt_id == NULL) return NULL_PTR;
+    if(sys_irqrmpolicy(interrupt_id)) return UNSBCR_ERROR;
+    return SUCCESS;
 }
 
 int16_t min(int16_t a, int16_t b){ return (b < a ? b : a); }
Index: proj/utils.h
===================================================================
--- proj/utils.h	(revision 144)
+++ proj/utils.h	(revision 145)
@@ -26,6 +26,14 @@
 int (util_sys_inb)(int port, uint8_t *value);
 
 /**
+ * @brief Unsubcribes Interrupts
+ * @param interrupt_id Interrupt ID, value via arguments on subscription of the interrupt_id
+ * @see subscribe_kbc_interrupt, subscribe_timer_interrupt
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int (unsubscribe_interrupt)(int *interrupt_id);
+
+/**
  * @brief Gets the minimum value out of two values.
  * @param a     First value
  * @param b     Second value
