Index: proj/Makefile
===================================================================
--- proj/Makefile	(revision 149)
+++ proj/Makefile	(revision 150)
@@ -1,6 +1,6 @@
 PROG=proj
 
-SRCS= proj.c graphics.c kbc.c keyboard.c utils.c timer.c
+SRCS= proj.c graphics.c kbc.c keyboard.c mouse.c utils.c timer.c
 
 CPPFLAGS += -pedantic -D __LCOM_OPTIMIZED_
 
Index: proj/mouse.c
===================================================================
--- proj/mouse.c	(nonexistent)
+++ proj/mouse.c	(revision 150)
@@ -0,0 +1,133 @@
+#include <lcom/lcf.h>
+
+#include "mouse.h"
+
+#include "errors.h"
+#include "kbc_macros.h"
+#include "mouse_macros.h"
+#include "kbc.h"
+
+int (subscribe_mouse_interrupt)(uint8_t interrupt_bit, int *interrupt_id) {
+    if (interrupt_id == NULL) return NULL_PTR;
+    *interrupt_id = interrupt_bit;
+    if (sys_irqsetpolicy(MOUSE_IRQ, IRQ_REENABLE | IRQ_EXCLUSIVE, interrupt_id)) return SBCR_ERROR;
+    return SUCCESS;
+}
+
+int got_error_mouse_ih = 0;
+int counter_mouse_ih = 0;
+
+void (mouse_ih)(void) {
+    uint8_t status = 0;
+    got_error_mouse_ih = 0;
+    if(counter_mouse_ih >= 3) counter_mouse_ih = 0;
+
+    if ((got_error_mouse_ih = util_sys_inb(STATUS_REG, &status))) return;
+
+    if (status & (TIME_OUT_REC | PARITY_ERROR)) {
+        got_error_mouse_ih = OTHER_ERROR;
+        return;
+    }
+    if (((status & AUX_MOUSE) == 0) || ((status & OUT_BUF_FUL) == 0)) {
+        got_error_mouse_ih = READ_ERROR;
+        return;
+    }
+
+    uint8_t byte = 0;
+
+    if ((got_error_mouse_ih = util_sys_inb(OUTPUT_BUF, &byte))) return;
+
+    /// This does not run if: I was expecting the first one but what I get is definitely not the first byte
+    if((byte & FIRST_BYTE_ID)  || counter_mouse_ih){
+        packet_mouse_ih[counter_mouse_ih++] = byte;
+    }
+}
+
+struct packet (mouse_parse_packet)(const uint8_t *packet_bytes){
+    struct packet pp;
+    pp.bytes[0] = packet_bytes[0];
+    pp.bytes[1] = packet_bytes[1];
+    pp.bytes[2] = packet_bytes[2];
+    pp.rb       = pp.bytes[0] & RIGHT_BUTTON;
+    pp.mb       = pp.bytes[0] & MIDDLE_BUTTON;
+    pp.lb       = pp.bytes[0] & LEFT_BUTTON;
+    pp.delta_x  = sign_extend_byte((packet_bytes[0] & MSB_X_DELTA) != 0, pp.bytes[1]);
+    pp.delta_y  = sign_extend_byte((packet_bytes[0] & MSB_Y_DELTA) != 0, pp.bytes[2]);
+    pp.x_ov     = pp.bytes[0] & X_OVERFLOW;
+    pp.y_ov     = pp.bytes[0] & Y_OVERFLOW;
+    return pp;
+}
+
+int mouse_poll(struct packet *pp, uint16_t period){
+    int ret = 0;
+
+    uint8_t packet[3];
+    uint8_t byte;
+    if ((ret = mouse_issue_cmd(READ_DATA))) return ret;
+    for(unsigned i = 0; i < 3; ++i){
+        if((ret = mouse_poll_byte(&byte, period))) return ret;
+        packet[i] = byte;
+    }
+    *pp = mouse_parse_packet(packet);
+    return SUCCESS;
+}
+
+int (mouse_set_data_report)(int on){
+    if(on) return mouse_issue_cmd(ENABLE_DATA_REP);
+    else   return mouse_issue_cmd(   DIS_DATA_REP);
+}
+
+int (mouse_read_data)(uint8_t *data, uint16_t period) {
+    int ret;
+    if ((ret = mouse_issue_cmd(READ_DATA))) return ret;
+    if ((ret = mouse_poll_byte(data, period))) return ret;
+    return SUCCESS;
+}
+
+int (mouse_issue_cmd)(uint32_t cmd) {
+    int ret;
+    uint8_t ack = 0;
+    for (unsigned int i = 0; i < KBC_NUM_TRIES; i++) {
+        if ((ret = kbc_issue_cmd(MOUSE_WRITE_B))) return ret;
+        if ((ret = kbc_issue_arg(cmd))) return ret;
+        if ((ret = mouse_read_byte(&ack))) return ret;
+
+        if (ack == ACK_OK) return SUCCESS;
+        if (ack == ACK_ERROR) return INVALID_COMMAND;
+        tickdelay(micros_to_ticks(DELAY));
+    }
+    return TIMEOUT_ERROR;
+}
+
+int (mouse_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)) {
+            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));
+    }
+    return TIMEOUT_ERROR;
+}
+
+int (mouse_poll_byte)(uint8_t *byte, uint16_t period) {
+    int ret = 0;
+    uint8_t stat;
+    while(true){
+        if((ret = util_sys_inb(STATUS_REG, &stat))) return ret;
+        if((stat&OUT_BUF_FUL) && (stat&AUX_MOUSE)) {
+            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));
+    }
+}
+
+int16_t (sign_extend_byte)(uint8_t sign_bit, uint8_t byte) {
+    return (int16_t)(((0xFF * sign_bit)<<8) | byte);
+}

Property changes on: proj/mouse.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/mouse.h
===================================================================
--- proj/mouse.h	(nonexistent)
+++ proj/mouse.h	(revision 150)
@@ -0,0 +1,91 @@
+#ifndef MOUSE_H_INCLUDED
+#define MOUSE_H_INCLUDED
+
+#include <stdint.h>
+
+/**
+ * @brief Subscribes Mouse Interrupts and disables Minix Default IH
+ * @param interrupt_bit Bit of Interrupt Vector that will be set when Mouse Interrupt is pending
+ * @param interrupt_id Mouse Interrupt ID to specify the Mouse Interrupt in other calls
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ * @see {_ERRORS_H_::errors}
+ */
+int (subscribe_mouse_interrupt)(uint8_t interrupt_bit, int *interrupt_id);
+
+//These have to do with mouse_ih
+int got_error_mouse_ih;
+uint8_t packet_mouse_ih[3];
+int counter_mouse_ih;
+
+/**
+ * @brief   Parse 3 bytes and returns it as a parsed, struct packet.
+ * @param   packet_bytes    array of bytes to parse
+ * @return  parsed struct packet
+ */
+struct packet (mouse_parse_packet)(const uint8_t *packet_bytes);
+
+/**
+ * @brief Polls mouse for data. Blocks execution until a valid mouse packet is obtained.
+ * @param   pp      pointer to packet struct in which the result will be stored
+ * @param   period  time (in milliseconds) the poller should wait between pollings of bytes
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int mouse_poll(struct packet *pp, uint16_t period);
+
+/**
+ * @brief Sets data report mode for mouse
+ * @param   on  zero to disable data report, any other value to enable data report
+ * @return  ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int (mouse_set_data_report)(int on);
+
+/**
+ * @brief Reads data byte from mouse
+ * <summary>
+ * Polls the mouse till data is available for reading
+ * </summary>
+ * @param data Pointer to variable where byte read from mouse will be stored
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ * @see {_ERRORS_H_::errors}
+ */
+int (mouse_read_data)(uint8_t *data, uint16_t period);
+
+/**
+ * @brief Issues command to mouse
+ * <summary>
+ * Issues command to mouse, returns error after two consecutive errors reported by the acknowledgment byte
+ * </summary>
+ * @param cmd Command to be issued
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ * @see {_ERRORS_H_::errors}
+ */
+int (mouse_issue_cmd)(uint32_t cmd);
+
+/**
+ * @brief Reads byte from mouse
+ * <summary>
+ * Reads byte from mouse, giving error if exceeds number of tries to read
+ * </summary>
+ * @param byte Pointer to variable where byte read from mouse will be stored
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ * @see {_ERRORS_H_::errors}
+ */
+int (mouse_read_byte)(uint8_t *byte);
+
+/**
+ * @brief Polls OUT_BUF for byte coming from mouse.
+ * @param   byte    pointer to byte read from OUT_BUF
+ * @param   period  time (in milliseconds) the poller should wait between pollings of bytes
+ * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
+ */
+int (mouse_poll_byte)(uint8_t *byte, uint16_t period);
+
+/**
+ * @brief Converts 9-bit number to 16-bit with sign extension
+ * @param sign_bit  Sign bit identifiying the signal of the number
+ * @param byte      Least significant byte that will be extended
+ * @return Extended 9-bit number
+ */
+int16_t (sign_extend_byte)(uint8_t sign_bit, uint8_t byte);
+
+#endif //MOUSE_H_INCLUDED

Property changes on: proj/mouse.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/mouse_macros.h
===================================================================
--- proj/mouse_macros.h	(nonexistent)
+++ proj/mouse_macros.h	(revision 150)
@@ -0,0 +1,37 @@
+#ifndef MOUSE_MACROS_H_INCLUDED
+#define MOUSE_MACROS_H_INCLUDED
+
+/* Mouse Data Packet */
+// Byte 0 - Button States
+#define LEFT_BUTTON     BIT(0) /* @brief Left button click event*/
+#define RIGHT_BUTTON    BIT(1) /* @brief Right button click event */
+#define MIDDLE_BUTTON   BIT(2) /* @brief Middle button click event */
+#define FIRST_BYTE_ID   BIT(3) /* @brief Identifier of first byte of packet CAREFUL: Not 100% accurate */
+#define MSB_X_DELTA     BIT(4) /* @brief Most significant bit of X delta */
+#define MSB_Y_DELTA     BIT(5) /* @brief Most significant bit of Y delta */
+#define X_OVERFLOW      BIT(6) /* @brief X delta overflowed */
+#define Y_OVERFLOW      BIT(7) /* @brief Y delta overflowed */
+// Byte 1 - X delta
+// Byte 2 - Y delta
+
+/* Mouse Commands */
+#define RESET           0xFF /* @brief Reset mouse */
+#define RESEND          0xFE /* @brief Resend command */
+#define DEFAULT         0xF6 /* @brief Set default values */
+#define DIS_DATA_REP    0xF5 /* @brief Disable Data Reporting */
+#define ENABLE_DATA_REP 0xF4 /* @brief Enable Data Reporting */
+#define SET_SAMPLE_RT   0xF3 /* @brief Sets state sampling rate */
+#define SET_REMOTE_MD   0xF0 /* @brief Sets Mouse on Remote Mode, data on request */
+#define READ_DATA       0xEB /* @brief Sends data packet request */
+#define SET_STREAM_MD   0xEA /* @brief Sets mouse on Stream Mode, data on events */
+#define STATUS_REQUEST  0xE9 /* @brief Get mouse configuration */
+#define SET_RESOLUTION  0xE8 /* @brief Sets resolution for mouse movement */
+#define SCALING_ACC_MD  0xE7 /* @brief Sets scaling on acceleration mode */
+#define SCALING_LIN_MD  0xE6 /* @brief Sets scaling on linear mode */
+
+/* Mouse Controller Responses */
+#define ACK_OK      0xFA /* @brief Operation sucessful */
+#define ACK_INVALID 0xFE /* @brief Invalid Byte, first occurence */
+#define ACK_ERROR   0xFC /* @brief Invalid Byte on resend */
+
+#endif // MOUSE_MACROS_H_INCLUDED

Property changes on: proj/mouse_macros.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: proj/proj.c
===================================================================
--- proj/proj.c	(revision 149)
+++ proj/proj.c	(revision 150)
@@ -8,6 +8,7 @@
 #include "i8254.h"
 #include "kbc_macros.h"
 #include "graphics_macros.h"
+#include "mouse_macros.h"
 #include "proj_macros.h"
 #include "errors.h"
 
@@ -15,6 +16,7 @@
 #include "graphics.h"
 #include "timer.h"
 #include "keyboard.h"
+#include "mouse.h"
 #include "utils.h"
 
 int main(int argc, char* argv[]) {
@@ -58,6 +60,16 @@
         return 1;
     }
 
+    /// Mouse interrupt handling
+    uint8_t mouse_irq_bit = MOUSE_IRQ;
+    int mouse_id = 0;
+    int mouse_irq = BIT(mouse_irq_bit);
+
+    if (subscribe_mouse_interrupt(mouse_irq_bit, &mouse_id)) return 1; // subscribes mouse interrupts in exclusive mode
+    if (sys_irqdisable(&mouse_id)) return 1; // temporarily disables our interrupts notifications
+    if (mouse_set_data_report(true)) return 1; // enables mouse data reporting
+    if (sys_irqenable(&mouse_id)) return 1; // re-enables our interrupts notifications
+
     /// cycle
     int good = 1;
     while (good) {
@@ -76,6 +88,10 @@
                     if (msg.m_notify.interrupts & timer_irq) { /* subscribed interrupt */
                         timer_int_handler();
                     }
+
+                    if (msg.m_notify.interrupts & mouse_irq) { /* subscribed interrupt */
+                        mouse_ih();
+                    }
                     break;
                 default:
                     break; /* no other notifications expected: do nothing */
@@ -95,5 +111,11 @@
         return 1;
     }
 
+    // Unsubscribe Mouse Interrupts
+    if (sys_irqdisable(&mouse_id)) return 1; // temporarily disables our interrupts notifications
+    if (mouse_set_data_report(false)) return 1; // enables mouse data reporting
+    if (sys_irqenable(&mouse_id)) return 1; // re-enables our interrupts notifications
+    if (unsubscribe_interrupt(&mouse_id)) return 1; // unsubscribes interrupts
+
     return 0;
 }
