Index: lab4/Makefile
===================================================================
--- lab4/Makefile	(revision 77)
+++ lab4/Makefile	(revision 78)
@@ -2,7 +2,7 @@
 PROG=lab4
 
 # source code files to be compiled
-SRCS = lab4.c mouse.c utils.c kbc.c keyboard.c timer.c
+SRCS = lab4.c mouse.c utils.c kbc.c keyboard.c timer.c state_machine.c
 
 # additional compilation flags
 # "-Wall -Wextra -Werror -I . -std=c11 -Wno-unused-parameter" are already set
Index: lab4/errors.h
===================================================================
--- lab4/errors.h	(revision 77)
+++ lab4/errors.h	(revision 78)
@@ -11,6 +11,7 @@
     WRITE_ERROR,        /* @brief Error on Writing to Port */
     TIMEOUT_ERROR,      /* @brief Timeout error */
     INVALID_COMMAND,    /* @brief Invalid Command issued */
+    INVALID_STATE,      /* @brief State machine reached an invalid state */
     OTHER_ERROR,        /* @brief Unspecified error */
 };
 
Index: lab4/kbc.c
===================================================================
--- lab4/kbc.c	(revision 77)
+++ lab4/kbc.c	(revision 78)
@@ -67,10 +67,9 @@
     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;//printf("kbc.c,L71\n");
-        printf("%x %d %d\n", stat, (stat&OUT_BUF_FUL), (stat&AUX_MOUSE));
-        if((stat&OUT_BUF_FUL) && (stat&AUX_MOUSE)==0){//printf("kbc.c,L72\n");
-            if(stat & (PARITY_ERROR | TIME_OUT_REC)) return OTHER_ERROR;//printf("kbc.c,L73\n");
+        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;
         }
Index: lab4/lab4.c
===================================================================
--- lab4/lab4.c	(revision 77)
+++ lab4/lab4.c	(revision 78)
@@ -7,7 +7,9 @@
 #include "kbc.h"
 #include "errors.h"
 #include "mouse_macros.h"
+#include "kbc_macros.h"
 #include "timer.h"
+#include "state_machine.h"
 
 int main(int argc, char *argv[]) {
   // sets the language of LCF messages (can be either EN-US or PT-PT)
@@ -95,6 +97,13 @@
     // return value
     int ret;
 
+    if ((ret = mouse_issue_cmd(SET_REMOTE_MD))) return ret;
+
+    if ((ret = mouse_set_data_report(true))) return ret;
+
+    uint8_t cmd = 0;
+    if ((ret = kbc_read_cmd(&cmd))) return ret;
+
     while (good) {
 
         if ((ret = mouse_read_data(&data))) return ret;
@@ -103,7 +112,6 @@
             packet[sz] = data;
             sz++;
         }
-
         if (sz == 3) {
             struct packet pp = mouse_parse_packet(packet);
             mouse_print_packet(&pp);
@@ -111,7 +119,6 @@
             sz = 0;
             if (packetCounter == cnt) good = 0;
         }
-
         tickdelay(micros_to_ticks(period*1e3));
     }
 
@@ -119,7 +126,6 @@
     if ((ret = mouse_issue_cmd(SET_STREAM_MD))) return ret;
     // Disable data reporting
     if ((ret = mouse_set_data_report(false))) return ret;
-
     uint8_t cmd_byte = minix_get_dflt_kbc_cmd_byte();
     if ((ret = kbc_change_cmd(cmd_byte))) return ret;
 
@@ -188,15 +194,7 @@
     return 0;
 }
 
-enum state{
-    STATE_NEUTRAL,
-    STATE_FIRST,
-    STATE_MID,
-    STATE_SECOND
-};
-
 int (mouse_test_gesture)(uint8_t x_len, uint8_t tolerance) {
-    int ret = 0;
     /// loop stuff
     int ipc_status, r;
     message msg;
@@ -205,13 +203,17 @@
     int mouse_id = 0;
     int mouse_irq = BIT(mouse_irq_bit);
     //if ((ret = mouse_set_data_report(true))) return ret;
-    if ((ret = mouse_enable_data_reporting())) return ret;
+    if (mouse_enable_data_reporting()) return 1;
 
     if (subscribe_mouse_interrupt(mouse_irq_bit, &mouse_id)) return 1;
     /// cycle
     int good = 1;
-    //int st = STATE_NEUTRAL;
-    //int16_t dx, dy;
+
+    // mouse event gesture
+    struct mouse_ev *event;
+    struct packet pp;
+    int response;
+
     while (good) {
         /* Get a request message. */
         if ((r = driver_receive(ANY, &msg, &ipc_status)) != 0) {
@@ -223,63 +225,17 @@
                 case HARDWARE: /* hardware interrupt notification */
                     if (msg.m_notify.interrupts & mouse_irq) { /* subscribed interrupt */
                         mouse_ih();
-                        if(counter >= 3){
-                            struct packet pp = mouse_parse_packet(packet);
-                            mouse_print_packet(&pp);/*
-                            switch(st){
-                                case STATE_NEUTRAL:
-                                    if(pp.lb == 1 && pp.mb == 0 && pp.rb == 0){
-                                        st = STATE_FIRST;
-                                        dx = 0;
-                                        dy = 0;
-                                    }
-                                    break;
-                                case STATE_FIRST:
-                                    if(pp.lb == 1){
-                                        if(pp.delta_x >= -tolerance && pp.delta_y >= -tolerance){
-                                            dx += pp.delta_x;
-                                            dy += pp.delta_y;
-                                        }else{
-                                            st = STATE_NEUTRAL;
-                                        }
-                                    }else{
-                                        if(abs(dx) < abs(dy) && dx > 0 && dy > 0){
-                                            st = STATE_MID;
-                                        }else{
-                                            st = STATE_NEUTRAL;
-                                        }
-                                    }
-                                    break;
-                                case STATE_MID:
-                                    if(pp.lb == 0 && pp.mb == 0 && pp.rb == 1){
-                                        st = STATE_SECOND;
-                                        dx = 0;
-                                        dy = 0;
-                                    }else{
-                                        st = STATE_NEUTRAL;
-                                    }
-                                    break;
-                                case STATE_SECOND:
-                                    if(pp.rb == 1){
-                                        if(pp.delta_x >= -tolerance && pp.delta_y <= tolerance){
-                                            dx += pp.delta_x;
-                                            dy += pp.delta_y;
-                                        }else{
-                                            st = STATE_NEUTRAL;
-                                        }
-                                    }else{
-                                        if(abs(dx) < abs(dy) && dx > 0 && dy < 0){
-                                            st = STATE_NEUTRAL;
-                                            good = false;
-                                        }else{
-                                            st = STATE_NEUTRAL;
-                                        }
-                                    }
-                                    break;
-                                default:
-                                    return OTHER_ERROR;
-                                    break;
-                            }*/
+                        if(counter >= 3) {
+                            pp = mouse_parse_packet(packet);
+                            //mouse_print_packet(&pp);
+                            event = mouse_get_event(&pp);
+
+                            response = state_machine(event, x_len, tolerance);
+
+                            if (response == SUCCESS)
+                                good = 0;
+                            else if (response == INVALID_STATE)
+                                return response;
                         }
                     }
                     break;
Index: lab4/mouse.c
===================================================================
--- lab4/mouse.c	(revision 77)
+++ lab4/mouse.c	(revision 78)
@@ -81,12 +81,16 @@
 int (mouse_issue_cmd)(uint32_t cmd) {
     int ret;
     uint8_t ack = 0;
-    if ((ret = kbc_issue_cmd(MOUSE_WRITE_B))) return ret;
-    if ((ret = kbc_issue_arg(cmd))) return ret;
-    if ((ret = mouse_read_ack(&ack))) return ret;
-    if (ack == ACK_OK) return SUCCESS;
-    if (ack == ACK_ERROR) return INVALID_COMMAND;
-    return OTHER_ERROR;
+    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_ack(&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) {
Index: lab4/state_machine.c
===================================================================
--- lab4/state_machine.c	(nonexistent)
+++ lab4/state_machine.c	(revision 78)
@@ -0,0 +1,166 @@
+#include <lcom/lcf.h>
+
+#include "state_machine.h"
+#include "mouse_macros.h"
+#include "mouse.h"
+#include "errors.h"
+
+struct mouse_ev* mouse_get_event(struct packet *pp) {
+
+    static struct mouse_ev event;
+    static struct packet last; // compare consecutive events
+    static int aux = 1; // first iteration
+
+    if (pp == NULL)
+        return &event;
+
+    // current packet
+    uint8_t lb_press = pp->bytes[0] & LEFT_BUTTON;
+    uint8_t rb_press = pp->bytes[0] & RIGHT_BUTTON;
+    uint8_t mb_press = pp->bytes[0] & MIDDLE_BUTTON;
+    int16_t delta_x = sign_extend_byte(pp->bytes[0] & MSB_X_DELTA, pp->bytes[1]);
+    int16_t delta_y = sign_extend_byte(pp->bytes[0] & MSB_Y_DELTA, pp->bytes[2]);
+
+    if (aux) { // first event detected
+        if (lb_press && (rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0)
+            event.type = LB_PRESSED;
+        else if (rb_press && (lb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0)
+            event.type = RB_PRESSED;
+        else if ((delta_x || delta_y) && (lb_press | rb_press | mb_press) == 0) {
+            event.type = MOUSE_MOV;
+            event.delta_x = delta_x;
+            event.delta_y = delta_y;
+        } else
+            event.type = BUTTON_EV;
+        aux = 0;
+    } else {
+        // last packet
+        uint8_t last_lb_press = last.bytes[0] & LEFT_BUTTON;
+        uint8_t last_rb_press = last.bytes[0] & RIGHT_BUTTON;
+        uint8_t last_mb_press = last.bytes[0] & MIDDLE_BUTTON;
+
+        if (lb_press && (rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_lb_press == 0)
+            event.type = LB_PRESSED;
+        else if (rb_press && (lb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_rb_press == 0)
+            event.type = RB_PRESSED;
+        else if ((lb_press | rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_lb_press)
+            event.type = LB_RELEASED;
+        else if ((lb_press | rb_press | mb_press) == 0 && delta_x == 0 && delta_y == 0 && last_rb_press)
+            event.type = RB_RELEASED;
+        else if ((delta_x || delta_y) && (lb_press | rb_press | mb_press) == (last_lb_press | last_rb_press | last_mb_press)) {
+            event.type = MOUSE_MOV;
+            event.delta_x = delta_x;
+            event.delta_y = delta_y;
+        } else
+            event.type = BUTTON_EV;
+    }
+
+    // update last packet for comparison
+    last = *pp;
+
+    return &event;
+}
+
+int state_machine(struct mouse_ev* event, uint8_t x_len, uint8_t tolerance) {
+
+    static enum states state = INITIAL;
+    static int response = OTHER_ERROR;
+    static int x_length = 0;
+    static int y_length = 0;
+
+    if (event == NULL)
+        return response;
+
+    switch (state) {
+        case INITIAL:
+            if (event->type == LB_PRESSED)
+                state = DRAG_UP;
+            break;
+        case DRAG_UP:
+            if (event->type == MOUSE_MOV) {
+                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance) {
+                    state = INITIAL;
+                    x_length = 0;
+                    y_length = 0;
+                    break;
+                }
+
+                x_length += event->delta_x;
+                y_length += event->delta_y;
+            } else if (event->type == LB_RELEASED) {
+                if (x_length == 0 || y_length == 0) {
+                    state = INITIAL;
+                    break;
+                }
+
+                int slope = y_length / x_length;
+
+                if (slope <= 1 || x_length < x_len) {
+                    state = INITIAL;
+                    x_length = 0;
+                    y_length = 0;
+                    break;
+                }
+
+                state = VERTEX;
+                x_length = 0;
+                y_length = 0;
+            } else {
+                state = INITIAL;
+                x_length = 0;
+                y_length = 0;
+            }
+            break;
+        case VERTEX:
+            if (event->type == MOUSE_MOV) {
+                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance)
+                    state = INITIAL;
+            } else if (event->type == RB_PRESSED) {
+                state = DRAG_DOWN;
+            } else if (event->type == LB_PRESSED) {
+                state = DRAG_UP;
+            } else
+                state = INITIAL;
+            break;
+        case DRAG_DOWN:
+            if (event->type == MOUSE_MOV) {
+                if (abs(event->delta_x) > tolerance || abs(event->delta_y) > tolerance) {
+                    state = INITIAL;
+                    x_length = 0;
+                    y_length = 0;
+                    break;
+                }
+
+                x_length += event->delta_x;
+                y_length += event->delta_y;
+            } else if (event->type == RB_RELEASED) {
+                if (x_length == 0 || y_length == 0) {
+                    state = INITIAL;
+                    break;
+                }
+
+                int slope = y_length / x_length;
+
+                if (slope >= -1 || x_length < x_len) {
+                    state = INITIAL;
+                    x_length = 0;
+                    y_length = 0;
+                    break;
+                }
+
+                state = FINAL;
+                x_length = 0;
+                y_length = 0;
+            } else {
+                state = INITIAL;
+                x_length = 0;
+                y_length = 0;
+            }
+            break;
+        case FINAL: // acception state
+            response = SUCCESS;
+        default: // invalid state / dead state
+            response = INVALID_STATE;
+    }
+    return response;
+}

Property changes on: lab4/state_machine.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: lab4/state_machine.h
===================================================================
--- lab4/state_machine.h	(nonexistent)
+++ lab4/state_machine.h	(revision 78)
@@ -0,0 +1,25 @@
+#ifndef _STATE_MACHINE_H_
+#define _STATE_MACHINE_H_
+
+/**
+ * @brief States of state machine
+ */
+enum states {
+    INITIAL,
+    DRAG_UP,
+    VERTEX,
+    DRAG_DOWN,
+    FINAL
+};
+
+/**
+ *
+ */
+struct mouse_ev* mouse_get_event(struct packet *pp);
+
+/**
+ *
+ */
+int state_machine(struct mouse_ev* event, uint8_t x_len, uint8_t tolerance);
+
+#endif /* end of include guard: _STATE_MACHINE_H_ */

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