~ruther/qmk_firmware

676d94d13791a99751cebf724fd5a56b150f344d — tmk 11 years ago 1591764
Fix PS/2 mouse support
5 files changed, 95 insertions(+), 84 deletions(-)

M common.mk
M common/keyboard.c
M protocol.mk
M protocol/pjrc.mk
M protocol/ps2_mouse.c
M common.mk => common.mk +1 -10
@@ 25,6 25,7 @@ endif
ifdef MOUSEKEY_ENABLE
    SRC += $(COMMON_DIR)/mousekey.c
    OPT_DEFS += -DMOUSEKEY_ENABLE
    OPT_DEFS += -DMOUSE_ENABLE
endif

ifdef EXTRAKEY_ENABLE


@@ 47,16 48,6 @@ ifdef NKRO_ENABLE
    OPT_DEFS += -DNKRO_ENABLE
endif

ifdef PS2_MOUSE_ENABLE
    SRC += $(COMMON_DIR)/ps2.c \
           $(COMMON_DIR)/ps2_mouse.c
    OPT_DEFS += -DPS2_MOUSE_ENABLE
endif

ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
    OPT_DEFS += -DMOUSE_ENABLE
endif

ifdef SLEEP_LED_ENABLE
    SRC += $(COMMON_DIR)/sleep_led.c
    OPT_DEFS += -DSLEEP_LED_ENABLE

M common/keyboard.c => common/keyboard.c +14 -1
@@ 30,8 30,13 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#include "sendchar.h"
#include "bootmagic.h"
#include "eeconfig.h"
#include "mousekey.h"
#include "backlight.h"
#ifdef MOUSEKEY_ENABLE
#   include "mousekey.h"
#endif
#ifdef PS2_MOUSE_ENABLE
#   include "ps2_mouse.h"
#endif


#ifdef MATRIX_HAS_GHOST


@@ 111,10 116,18 @@ void keyboard_task(void)
    action_exec(TICK);

MATRIX_LOOP_END:

#ifdef MOUSEKEY_ENABLE
    // mousekey repeat & acceleration
    mousekey_task();
#endif

#ifdef PS2_MOUSE_ENABLE
    if (ps2_mouse_read() == 0) {
        ps2_mouse_usb_send();
    }
#endif

    // update LED
    if (led_status != host_keyboard_leds()) {
        led_status = host_keyboard_leds();

M protocol.mk => protocol.mk +25 -0
@@ 1,2 1,27 @@
PROTOCOL_DIR = protocol


ifdef PS2_MOUSE_ENABLE
    SRC += $(PROTOCOL_DIR)/ps2_mouse.c
    OPT_DEFS += -DPS2_MOUSE_ENABLE
    OPT_DEFS += -DMOUSE_ENABLE
endif

ifdef PS2_USE_BUSYWAIT
    SRC += protocol/ps2.c
    OPT_DEFS += -DPS2_USE_BUSYWAIT
endif

ifdef PS2_USE_INT
    SRC += protocol/ps2.c
    OPT_DEFS += -DPS2_USE_INT
endif

ifdef PS2_USE_USART
    SRC += protocol/ps2_usart.c
    OPT_DEFS += -DPS2_USE_USART
endif


# Search Path
VPATH += $(TOP_DIR)/protocol

M protocol/pjrc.mk => protocol/pjrc.mk +5 -1
@@ 7,7 7,11 @@ SRC +=	$(PJRC_DIR)/main.c \
	$(PJRC_DIR)/usb.c

# Option modules
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
ifdef MOUSEKEY_ENABLE
    SRC += $(PJRC_DIR)/usb_mouse.c
endif

ifdef PS2_MOUSE_ENABLE
    SRC += $(PJRC_DIR)/usb_mouse.c
endif


M protocol/ps2_mouse.c => protocol/ps2_mouse.c +50 -72
@@ 1,5 1,5 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
Copyright 2011,2013 Jun Wako <wakojun@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by


@@ 32,27 32,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#   define phex16(h)
#endif

// disable when errors occur 255 times.
#define ERROR_RETURN() do { \
    if (ps2_error) { \
        if (ps2_mouse_error_count < 255) { \
            ps2_mouse_error_count++; \
        } else { \
            ps2_mouse_error_count = 0; \
            ps2_mouse_enable = false; \
        } \
        return ps2_error; \
    } \
} while (0)


/*
TODO
----
- Stream mode
- Tracpoint command support: needed
- Middle button + move = Wheel traslation
*/
bool ps2_mouse_enable = true;
uint8_t ps2_mouse_x = 0;
uint8_t ps2_mouse_y = 0;


@@ 69,85 49,50 @@ uint8_t ps2_mouse_init(void) {

    ps2_host_init();

    // Reset
    rcv = ps2_host_send(0xFF);
    print("ps2_mouse_init: send 0xFF: ");
    phex(ps2_error); print("\n");
    ERROR_RETURN();
    // Not reliable: sometime fail to initialize mouse

    // ACK
    rcv = ps2_host_recv();
    print("ps2_mouse_init: read ACK: ");
    // send Reset
    _delay_ms(1000);    // wait for powering up
    rcv = ps2_host_send(0xFF);
    print("ps2_mouse_init: send Reset: ");
    phex(rcv); phex(ps2_error); print("\n");
    ERROR_RETURN();

    // BAT takes some time
    _delay_ms(100);
    // read completion code of BAT
    //_delay_ms(1000);    // wait for Basic Assurance Test
    rcv = ps2_host_recv();
    print("ps2_mouse_init: read BAT: ");
    phex(rcv); phex(ps2_error); print("\n");
    ERROR_RETURN();

    // Device ID
    // read Device ID
    rcv = ps2_host_recv();
    print("ps2_mouse_init: read DevID: ");
    phex(rcv); phex(ps2_error); print("\n");
    ERROR_RETURN();

    // Enable data reporting
    ps2_host_send(0xF4);
    // send Enable Data Reporting
    rcv = ps2_host_send(0xF4);
    print("ps2_mouse_init: send 0xF4: ");
    phex(ps2_error); print("\n");
    ERROR_RETURN();

    // ACK
    rcv = ps2_host_recv();
    print("ps2_mouse_init: read ACK: ");
    phex(rcv); phex(ps2_error); print("\n");
    ERROR_RETURN();

    // Set Remote mode
    ps2_host_send(0xF0);
    // send Set Remote mode
    rcv = ps2_host_send(0xF0);
    print("ps2_mouse_init: send 0xF0: ");
    phex(ps2_error); print("\n");
    ERROR_RETURN();

    // ACK
    rcv = ps2_host_recv();
    print("ps2_mouse_init: read ACK: ");
    phex(rcv); phex(ps2_error); print("\n");
    ERROR_RETURN();

    return 0;
}

/*
Data format:
    bit: 7       6       5       4       3       2       1       0
-----------------------------------------------------------------------
0   btn: Yovflw  Xovflw  Ysign   Xsign   1       Middle  Right   Left
1   x:   X movement(0-255)
2   y:   Y movement(0-255)
*/
uint8_t ps2_mouse_read(void)
{
    uint8_t rcv;

    if (!ps2_mouse_enable) return 1;

    ps2_host_send(0xEB);
    ERROR_RETURN();

    rcv=ps2_host_recv();
    ERROR_RETURN();
    rcv = ps2_host_send(0xEB);

    if(rcv==0xFA) {
        ps2_mouse_btn = ps2_host_recv();
        ERROR_RETURN();
        ps2_mouse_x = ps2_host_recv();
        ERROR_RETURN();
        ps2_mouse_y = ps2_host_recv();
        ERROR_RETURN();
        ps2_mouse_btn = ps2_host_recv_response();
        ps2_mouse_x = ps2_host_recv_response();
        ps2_mouse_y = ps2_host_recv_response();
    }
    return 0;
}


@@ 216,3 161,36 @@ void ps2_mouse_print(void)
    phex(ps2_mouse_x); print(" ");
    phex(ps2_mouse_y); print("\n");
}


/* PS/2 Mouse Synopsis
 * http://www.computer-engineering.org/ps2mouse/
 *
 * Command:
 * 0xFF: Reset
 * 0xF6: Set Defaults Sampling; rate=100, resolution=4cnt/mm, scaling=1:1, reporting=disabled
 * 0xF5: Disable Data Reporting
 * 0xF4: Enable Data Reporting
 * 0xF3: Set Sample Rate
 * 0xF2: Get Device ID
 * 0xF0: Set Remote Mode
 * 0xEB: Read Data
 * 0xEA: Set Stream Mode
 * 0xE9: Status Request
 * 0xE8: Set Resolution
 * 0xE7: Set Scaling 2:1
 * 0xE6: Set Scaling 1:1
 *
 * Mode:
 * Stream Mode: devices sends the data when it changs its state
 * Remote Mode: host polls the data periodically
 *
 * This code uses Remote Mode and polls the data with Read Data(0xEB).
 *
 * Data format:
 * byte|7       6       5       4       3       2       1       0
 * ----+--------------------------------------------------------------
 *    0|Yovflw  Xovflw  Ysign   Xsign   1       Middle  Right   Left
 *    1|                    X movement(0-255)
 *    2|                    Y movement(0-255)
 */