Index: lab5/Makefile
===================================================================
--- lab5/Makefile	(revision 108)
+++ lab5/Makefile	(revision 109)
@@ -2,7 +2,7 @@
 PROG=lab5
 
 # source code files to be compiled
-SRCS = lab5.c graphics.c
+SRCS = lab5.c graphics.c keyboard.c kbc.c utils.c
 
 # additional compilation flags
 # "-Wall -Wextra -Werror -I . -std=c11 -Wno-unused-parameter" are already set
Index: lab5/graphics.c
===================================================================
--- lab5/graphics.c	(revision 108)
+++ lab5/graphics.c	(revision 109)
@@ -123,15 +123,16 @@
 }
 
 int (vg_draw_hline)(uint16_t x, uint16_t y, uint16_t len, uint32_t color){
+    int r;
+    for (int i = 0; i < len; i++)
+        if ((r = set_pixel(x + i, y, color))) return r;
 
+    return SUCCESS;
+
     //uint8_t color8 = color;
-    for(uint32_t i = 0; i < 256; ++i){
-        set_pixel(x+i,y,i);
-    }/*
-    set_pixel(x,y,0);
-    set_pixel(x+1,y,1);
-    set_pixel(x+2,y,2);
-    */
+    //set_pixel(x,y,color);
+    //set_pixel(x+1,y,color);
+    //set_pixel(x+2,y,color);
     //*(p++) = color8;
     //*(p++) = color8;
     //*(p++) = color8;
@@ -145,5 +146,12 @@
         *((uint8_t*)(video_mem)+y*1024+x+len) = color8;
     }
     */
-    return 0;
 }
+
+int (vg_draw_rectangle)(uint16_t x, uint16_t y,uint16_t width, uint16_t height, uint32_t color)	{
+    int r;
+    for (int i = 0; i < height; i++)
+        if ((r = vg_draw_hline(x, y + i, width, color))) return r;
+
+    return SUCCESS;
+}
Index: lab5/kbc.c
===================================================================
--- lab5/kbc.c	(nonexistent)
+++ lab5/kbc.c	(revision 109)
@@ -0,0 +1,80 @@
+#include <lcom/lcf.h>
+
+#include "kbc.h"
+
+#include "kbc_macros.h"
+#include "utils.h"
+#include "errors.h"
+
+int (unsubscribe_interrupt)(int *interrupt_id) {
+    if (interrupt_id == NULL) return NULL_PTR;
+    if(sys_irqrmpolicy(interrupt_id)) return UNSBCR_ERROR;
+    return SUCCESS;
+}
+
+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: lab5/kbc.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab5/kbc.h
===================================================================
--- lab5/kbc.h	(nonexistent)
+++ lab5/kbc.h	(revision 109)
@@ -0,0 +1,63 @@
+/**
+ * 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 Unsubcribes Interrupts
+ * @param interrupt_id Interrupt ID, value via arguments on subscription of the interrupt_id
+ * @see subscribe_kbc_interrupt, subscribe_timer_interrupt
+ * @return Whether operation was sucessful or not
+ */
+int (unsubscribe_interrupt)(int *interrupt_id);
+
+/**
+ * @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: lab5/kbc.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab5/kbc_macros.h
===================================================================
--- lab5/kbc_macros.h	(nonexistent)
+++ lab5/kbc_macros.h	(revision 109)
@@ -0,0 +1,56 @@
+#ifndef KBC_MACROS_H_INCLUDED
+#define KBC_MACROS_H_INCLUDED
+
+/* KBC IRQ Line */
+
+#define KBC_IRQ     1   /* @brief KBC Controller IRQ Line */
+#define MOUSE_IRQ   12  /* @brief Mouse IRQ Line */
+
+/* Delay for KBC */
+#define DELAY           20000 /* @brief KBC Response Delay */
+#define KBC_NUM_TRIES   20    /* @brief Number of tries to issue command before timeout */
+
+/* I/O Ports Addresses */
+
+#define KBC_CMD     0x64 /* @brief Address to send commands to KBC */
+#define KBC_CMD_ARG 0x60 /* @brief Address to write KBC Command Arguments */
+#define STATUS_REG  0x64 /* @brief KBC Status Register address */
+
+#define OUTPUT_BUF  0x60 /* @brief Address of Output Buffer of KBC */
+
+/* KBC Commands */
+#define READ_KBC_CMD    0x20 /* @brief Read KBC Command Byte */
+#define WRITE_KBC_CMD   0x60 /* @brief Write KBC Command Byte */
+#define KBC_SELF_TEST   0xAA /* @brief KBC Diagnostic Tests */
+#define KBC_INT_TEST    0xAB /* @brief Tests Keyboard Clock and Data lines */
+#define KBC_INT_DISABLE 0xAD /* @brief Disable KBC Interface */
+#define KBC_INT_ENABLE  0xAE /* @brief Enable KBC Interface */
+#define MOUSE_DISABLE   0xA7 /* @brief Disable Mouse */
+#define MOUSE_ENABLE    0xA8 /* @brief Enable Mouse */
+#define MOUSE_INT_TEST  0xA9 /* @brief Tests Mouse data line */
+#define MOUSE_WRITE_B   0xD4 /* @brief Write a byte directly to the mouse */
+
+/* Status Byte Masking */
+
+#define OUT_BUF_FUL     BIT(0) /* @brief Output Buffer State */
+#define IN_BUF_FULL     BIT(1) /* @brief Input Buffer State */
+#define SYS_FLAG        BIT(2) /* @brief System Flag */
+#define DATA_CMD_WRITE  BIT(3) /* @brief Identifier of type of byte in input buffer */
+#define INH_FLAG        BIT(4) /* @brief Keyboard inihibited */
+#define AUX_MOUSE       BIT(5) /* @brief Mouse Data */
+#define TIME_OUT_REC    BIT(6) /* @brief Time Out Error - Invalid Data */
+#define PARITY_ERROR    BIT(7) /* @brief Parity Error - Invalid Data */
+
+/* Scancode Constants */
+
+#define ESC_BREAK_CODE  0x81    /* @brief ESC Break Code */
+#define TWO_BYTE_CODE   0xE0    /* @brief First byte of a two byte Scancode */
+#define BREAK_CODE_BIT  BIT(7)  /* @brief Bit to distinguish between Make code and Break code */
+
+/* Command byte masks */
+#define INT_KBD         BIT(0)  /* @brief Enable Keyboard Interrupts */
+#define INT_MOU         BIT(1)  /* @brief Enable Mouse Interrupts */
+#define DIS_KBD         BIT(4)  /* @brief Disable Keyboard */
+#define DIS_MOU         BIT(5)  /* @brief Disable Mouse */
+
+#endif //KBC_MACROS_H_INCLUDED

Property changes on: lab5/kbc_macros.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab5/keyboard.c
===================================================================
--- lab5/keyboard.c	(nonexistent)
+++ lab5/keyboard.c	(revision 109)
@@ -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: lab5/keyboard.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab5/keyboard.h
===================================================================
--- lab5/keyboard.h	(nonexistent)
+++ lab5/keyboard.h	(revision 109)
@@ -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: lab5/keyboard.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab5/lab5.c
===================================================================
--- lab5/lab5.c	(revision 108)
+++ lab5/lab5.c	(revision 109)
@@ -7,6 +7,9 @@
 
 #include "graphics.h"
 #include "graphics_macros.h"
+#include "keyboard.h"
+#include "kbc.h"
+#include "kbc_macros.h"
 
 // Any header files included below this line should have been created by you
 
@@ -39,13 +42,6 @@
     if ((r = get_permissions_first_mbyte()))
         panic("%s: sys_privctl (ADD MEM) failed: %d\n", __func__, r);
 
-    if (set_graphics_mode(mode)) {
-        printf("%s: failed to set graphic mode %x.\n", __func__, mode);
-        if (vg_exit())
-            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
-        return 1;
-    };
-
     if (vbe_get_mode_information(mode)) {
         printf("%s: failed to get information for mode %x.\n", __func__, mode);
         if (vg_exit())
@@ -55,6 +51,13 @@
 
     map_vram(); // if function fails it aborts program
 
+    if (set_graphics_mode(mode)) {
+        printf("%s: failed to set graphic mode %x.\n", __func__, mode);
+        if (vg_exit())
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+        return 1;
+    };
+
     tickdelay(micros_to_ticks(delay*1e6));
 
     if (vg_exit()) {
@@ -76,8 +79,17 @@
 int(video_test_rectangle)(uint16_t mode, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color) {
     int r;
     if ((r = get_permissions_first_mbyte()))
-    panic("%s: sys_privctl (ADD MEM) failed: %d\n", __func__, r);
+        panic("%s: sys_privctl (ADD MEM) failed: %d\n", __func__, r);
 
+    if (vbe_get_mode_information(mode)) {
+        printf("%s: failed to get information for mode %x.\n", __func__, mode);
+        if (vg_exit())
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+        return 1;
+    }
+
+    map_vram(); // if function fails it aborts program
+
     if (set_graphics_mode(mode)) {
         printf("%s: failed to set graphic mode %x.\n", __func__, mode);
         if (vg_exit()) printf("%s: vg_exit failed to exit to text mode.\n", __func__);
@@ -84,13 +96,71 @@
         return 1;
     };
 
-    vg_draw_hline(x, y, width, color);
-    tickdelay(micros_to_ticks(1000000));
+    if (vg_draw_rectangle(x, y, width, height, color)) {
+        if (vg_exit()) {
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+            if (free_memory()) printf("%s: lm_free failed\n", __func__);
+        }
+        return 1;
+    }
+
+    /// loop stuff
+    int ipc_status;
+    message msg;
+    /// Keyboard interrupt handling
+    uint8_t kbc_irq_bit = KBC_IRQ;
+    int kbc_id = 0;
+    int kbc_irq = BIT(kbc_irq_bit);
+    if (subscribe_kbc_interrupt(kbc_irq_bit, &kbc_id)) {
+        if (vg_exit()) {
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+            if (free_memory()) printf("%s: lm_free failed\n", __func__);
+        }
+        return 1;
+    }
+    /// cycle
+    int good = 1;
+    while (good) {
+        /* Get a request message. */
+        if ((r = driver_receive(ANY, &msg, &ipc_status)) != 0) {
+            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 & kbc_irq) { /* subscribed interrupt */
+                        kbc_ih();
+                        if (scancode[0] == ESC_BREAK_CODE) good = 0;
+                    }
+                    break;
+                default:
+                    break; /* no other notifications expected: do nothing */
+            }
+        } else { /* received standart message, not a notification */
+            /* no standart message expected: do nothing */
+        }
+    }
+
+    if (unsubscribe_interrupt(&kbc_id)) {
+        if (vg_exit()) {
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+            if (free_memory()) printf("%s: lm_free failed\n", __func__);
+        }
+        return 1;
+    };
+
     if (vg_exit()) {
         printf("%s: vg_exit failed to exit to text mode.\n", __func__);
         if (free_memory()) printf("%s: lm_free failed\n", __func__);
         return 1;
     }
+
+    if (free_memory()) {
+        printf("%s: lm_free failed\n", __func__);
+        return 1;
+    }
+
     return 0;
 }
 
Index: lab5/utils.c
===================================================================
--- lab5/utils.c	(nonexistent)
+++ lab5/utils.c	(revision 109)
@@ -0,0 +1,37 @@
+#include <lcom/lcf.h>
+
+#include "utils.h"
+
+#include <stdint.h>
+#include "errors.h"
+
+int(util_get_LSB)(uint16_t val, uint8_t *lsb) {
+    if (lsb == NULL) return NULL_PTR;
+    *lsb = val;
+    return SUCCESS;
+}
+
+int(util_get_MSB)(uint16_t val, uint8_t *msb) {
+    if (msb == NULL) return NULL_PTR;
+    *msb = (val >> 8);
+    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;
+    if(sys_inb(port, &n)) return READ_ERROR;
+    *value = n;
+    #ifdef LAB3
+        ++sys_inb_counter;
+    #endif
+    return SUCCESS;
+}
+
+int16_t abs16(int16_t x) {
+    return (x >= 0) ? (int16_t)(x) : (int16_t)(-x);
+}

Property changes on: lab5/utils.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab5/utils.h
===================================================================
--- lab5/utils.h	(nonexistent)
+++ lab5/utils.h	(revision 109)
@@ -0,0 +1,32 @@
+#ifndef UTILS_H_INCLUDED
+#define UTILS_H_INCLUDED
+
+/**
+ * @brief Gets the least significant byte of a 16-bit variable
+ * @param val 16-bit variable
+ * @param lsb Pointer to a 8-bit variable to store the value of the LSB
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int(util_get_LSB)(uint16_t val, uint8_t *lsb);
+
+/**
+ * @brief Gets the most significant byte of a 16-bit variable
+ * @param val 16-bit variable
+ * @param lsb Pointer to a 8-bit variable to store the value of the MSB
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int(util_get_MSB)(uint16_t val, uint8_t *msb);
+
+#ifdef LAB3
+    uint32_t sys_inb_counter;
+#endif
+
+/**
+ * @brief sys_inb wrapper
+ * @param port Port to read from
+ * @param value Pointer to byte to store value read
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int (util_sys_inb)(int port, uint8_t *value);
+
+#endif //UTILS_H_INCLUDED

Property changes on: lab5/utils.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
