<commit_before>//=======================================================================
// Copyright <NAME> 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithms.hpp>

#include "mouse.hpp"
#include "interrupts.hpp"
#include "kernel_utils.hpp"
#include "logging.hpp"
#include "vesa.hpp"
#include "terminal.hpp"

namespace {

#ifdef THOR_CONFIG_MOUSE_VERBOSE
#define verbose_logf(...) logging::logf(__VA_ARGS__)
#else
#define verbose_logf(...)
#endif

constexpr const uint16_t DATA_PORT = 0x60;
constexpr const uint16_t STATUS_PORT = 0x64;

uint8_t cycle = 0; // The interrupt cycles through different information

uint8_t previous_flags = 0;
uint8_t mouse_packet[3];
uint16_t position_x = 0;
uint16_t position_y = 0;

void mouse_handler(interrupt::syscall_regs*, void*){
    mouse_packet[cycle++] = in_byte(DATA_PORT);

    if(cycle == 1){ // was 0
        int8_t flags = mouse_packet[0];

        // If bit 3 is not set, drop the packet
        if((flags & (1 << 3)) == 0){
            cycle = 0;
            return;
        }
    }

    if(cycle == 3){
        cycle = 0;

        int8_t flags = mouse_packet[0];

        // Discard overflow packets
        if(flags & ((1 << 6) | (1 << 7))){
            return;
        }

        // Compute the 9bit delta values
        int16_t delta_x = mouse_packet[1] - ((flags << 4) & 0x100);
        int16_t delta_y = mouse_packet[2] - ((flags << 3) & 0x100);

        // Reverse the y direction
        delta_y = -delta_y;

        if(delta_y || delta_x){
            position_x = std::max(int16_t(position_x) + delta_x, 0);
            position_y = std::max(int16_t(position_y) + delta_y, 0);

            if(vesa::enabled()){
                position_x = std::min(position_x, uint16_t(vesa::get_width()));
                position_y = std::min(position_y, uint16_t(vesa::get_height()));
            }

            verbose_logf(logging::log_level::TRACE, "mouse: moved %d:%d \n", int64_t(position_x), int64_t(position_y));
        }

        if((flags & (1 << 0)) && !(previous_flags & (1 << 0))){
            verbose_logf(logging::log_level::TRACE, "mouse: left button pressed %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_LEFT_PRESS);
        }

        if((flags & (1 << 1)) && !(previous_flags & (1 << 1))){
            verbose_logf(logging::log_level::TRACE, "mouse: right button pressed %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_RIGHT_PRESS);
        }

        if(!(flags & (1 << 0)) && (previous_flags & (1 << 0))){
            verbose_logf(logging::log_level::TRACE, "mouse: left button released %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_LEFT_RELEASE);
        }

        if(!(flags & (1 << 1)) && (previous_flags & (1 << 1))){
            verbose_logf(logging::log_level::TRACE, "mouse: right button released %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_LEFT_RELEASE);
        }

        previous_flags = flags;
    }
}

void ps2_data_wait(){
    auto timeout = 100000;
    while(timeout-- && (in_byte(STATUS_PORT) & 1) != 1){}
}<commit_msg>Fix mouse driver<commit_after>//=======================================================================
// Copyright <NAME> 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithms.hpp>

#include "mouse.hpp"
#include "interrupts.hpp"
#include "kernel_utils.hpp"
#include "logging.hpp"
#include "vesa.hpp"
#include "terminal.hpp"

namespace {

#ifdef THOR_CONFIG_MOUSE_VERBOSE
#define verbose_logf(...) logging::logf(__VA_ARGS__)
#else
#define verbose_logf(...)
#endif

constexpr const uint16_t DATA_PORT = 0x60;
constexpr const uint16_t STATUS_PORT = 0x64;

uint8_t cycle = 0; // The interrupt cycles through different information

uint8_t previous_flags = 0;
uint8_t mouse_packet[3];
uint16_t position_x = 0;
uint16_t position_y = 0;

void mouse_handler(interrupt::syscall_regs*, void*){
    mouse_packet[cycle++] = in_byte(DATA_PORT);

    if(cycle == 1){ // was 0
        int8_t flags = mouse_packet[0];

        // If bit 3 is not set, drop the packet
        if((flags & (1 << 3)) == 0){
            cycle = 0;
            return;
        }
    }

    if(cycle == 3){
        cycle = 0;

        int8_t flags = mouse_packet[0];

        // Discard overflow packets
        if(flags & ((1 << 6) | (1 << 7))){
            return;
        }

        // Compute the 9bit delta values
        int16_t delta_x = mouse_packet[1] - ((flags << 4) & 0x100);
        int16_t delta_y = mouse_packet[2] - ((flags << 3) & 0x100);

        // Reverse the y direction
        delta_y = -delta_y;

        if(delta_y || delta_x){
            position_x = std::max(int16_t(position_x) + delta_x, 0);
            position_y = std::max(int16_t(position_y) + delta_y, 0);

            if(vesa::enabled()){
                position_x = std::min(position_x, uint16_t(vesa::get_width()));
                position_y = std::min(position_y, uint16_t(vesa::get_height()));
            }

            verbose_logf(logging::log_level::TRACE, "mouse: moved %d:%d \n", int64_t(position_x), int64_t(position_y));
        }

        if((flags & (1 << 0)) && !(previous_flags & (1 << 0))){
            verbose_logf(logging::log_level::TRACE, "mouse: left button pressed %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_LEFT_PRESS);
        }

        if(!(flags & (1 << 0)) && (previous_flags & (1 << 0))){
            verbose_logf(logging::log_level::TRACE, "mouse: left button released %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_LEFT_RELEASE);
        }

        if((flags & (1 << 1)) && !(previous_flags & (1 << 1))){
            verbose_logf(logging::log_level::TRACE, "mouse: right button pressed %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_RIGHT_PRESS);
        }

        if(!(flags & (1 << 1)) && (previous_flags & (1 << 1))){
            verbose_logf(logging::log_level::TRACE, "mouse: right button released %d:%d \n", int64_t(position_x), int64_t(position_y));

            stdio::get_active_terminal().send_mouse_input(keycode::MOUSE_RIGHT_RELEASE);
        }

        previous_flags = flags;
    }
}

void ps2_data_wait(){
    auto timeout = 100000;
    while(timeout-- && (in_byte(STATUS_PORT) & 1) != 1){}
}
{'fraction_non_alphanumeric': 0.18645980253878702, 'fraction_numerical': 0.03526093088857546, 'mean_word_length': 3.0823258491652274, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5790663', 'n_tokens_mistral': 2559, 'n_tokens_neox': 2319, 'n_words': 482}