mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 07:55:56 +00:00
advanced ps/2 mouse driver that supports intellimouse and mice with mouse wheel and 4th and 5th buttons
svn path=/trunk/; revision=6173
This commit is contained in:
parent
7871924668
commit
9a74edf2a1
8 changed files with 1313 additions and 440 deletions
239
reactos/drivers/input/psaux/logips2pp.c
Normal file
239
reactos/drivers/input/psaux/logips2pp.c
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Logitech PS/2++ mouse driver
|
||||
*
|
||||
* Copyright (c) 1999-2003 Vojtech Pavlik <vojtech@suse.cz>
|
||||
* Copyright (c) 2003 Eric Wong <eric@yhbt.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/ntddmou.h>
|
||||
#include "mouse.h"
|
||||
#include "logips2pp.h"
|
||||
|
||||
/*
|
||||
* Process a PS2++ or PS2T++ packet.
|
||||
*/
|
||||
|
||||
void ps2pp_process_packet(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input)
|
||||
{
|
||||
unsigned char *packet = DeviceExtension->MouseBuffer;
|
||||
|
||||
if ((packet[0] & 0x48) == 0x48 && (packet[1] & 0x02) == 0x02) {
|
||||
|
||||
switch ((packet[1] >> 4) | (packet[0] & 0x30)) {
|
||||
|
||||
case 0x0d: /* Mouse extra info */
|
||||
|
||||
/* FIXME - mouse seems to have 2 wheels
|
||||
input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
|
||||
(int) (packet[2] & 8) - (int) (packet[2] & 7)); */
|
||||
|
||||
Input->ButtonData = (UINT)((WHEEL_DELTA) * ((int)(packet[2] & 8) - (int)(packet[2] & 7)));
|
||||
Input->RawButtons |= ((packet[2] >> 4) & 1) ? GPM_B_FOURTH : 0;
|
||||
Input->RawButtons |= ((packet[2] >> 5) & 1) ? GPM_B_FIFTH : 0;
|
||||
|
||||
break;
|
||||
|
||||
case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */
|
||||
|
||||
Input->RawButtons |= (packet[2] & 1) ? GPM_B_FOURTH : 0;
|
||||
Input->RawButtons |= ((packet[2] >> 1) & 1) ? GPM_B_FIFTH : 0;
|
||||
|
||||
/* FIXME - support those buttons???
|
||||
input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1);
|
||||
input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1);
|
||||
input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1);
|
||||
*/
|
||||
|
||||
break;
|
||||
|
||||
case 0x0f: /* TouchPad extra info */
|
||||
|
||||
/* FIXME - mouse seems to have 2 wheels
|
||||
input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
|
||||
(int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); */
|
||||
|
||||
Input->ButtonData = (UINT)((WHEEL_DELTA) *((int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)));
|
||||
|
||||
packet[0] = packet[2] | 0x08;
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgPrint("logips2pp.c: Received PS2++ packet 0x%x, but don't know how to handle.\n",
|
||||
(packet[1] >> 4) | (packet[0] & 0x30));
|
||||
}
|
||||
|
||||
packet[0] &= 0x0f;
|
||||
packet[1] = 0;
|
||||
packet[2] = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ps2pp_cmd() sends a PS2++ command, sliced into two bit
|
||||
* pieces through the SETRES command. This is needed to send extended
|
||||
* commands to mice on notebooks that try to understand the PS/2 protocol
|
||||
* Ugly.
|
||||
*/
|
||||
|
||||
static int ps2pp_cmd(PDEVICE_EXTENSION DeviceExtension, unsigned char *param, unsigned char command)
|
||||
{
|
||||
unsigned char d;
|
||||
int i;
|
||||
|
||||
if (psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11))
|
||||
return -1;
|
||||
|
||||
for (i = 6; i >= 0; i -= 2) {
|
||||
d = (command >> i) & 3;
|
||||
if(psmouse_command(DeviceExtension, &d, PSMOUSE_CMD_SETRES))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (psmouse_command(DeviceExtension, param, PSMOUSE_CMD_POLL))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SmartScroll / CruiseControl for some newer Logitech mice Defaults to
|
||||
* enabled if we do nothing to it. Of course I put this in because I want it
|
||||
* disabled :P
|
||||
* 1 - enabled (if previously disabled, also default)
|
||||
* 0/2 - disabled
|
||||
*/
|
||||
|
||||
static void ps2pp_set_smartscroll(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[4];
|
||||
|
||||
ps2pp_cmd(DeviceExtension, param, 0x32);
|
||||
|
||||
param[0] = 0;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
|
||||
if (DeviceExtension->psmouse_smartscroll == 1)
|
||||
param[0] = 1;
|
||||
else
|
||||
if (DeviceExtension->psmouse_smartscroll > 2)
|
||||
return;
|
||||
|
||||
/* else leave param[0] == 0 to disable */
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support 800 dpi resolution _only_ if the user wants it (there are good
|
||||
* reasons to not use it even if the mouse supports it, and of course there are
|
||||
* also good reasons to use it, let the user decide).
|
||||
*/
|
||||
|
||||
void ps2pp_set_800dpi(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param = 3;
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, ¶m, PSMOUSE_CMD_SETRES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or
|
||||
* touchpad.
|
||||
*/
|
||||
|
||||
int ps2pp_detect_model(PDEVICE_EXTENSION DeviceExtension, unsigned char *param)
|
||||
{
|
||||
int i;
|
||||
//char *vendor, *name;
|
||||
static int logitech_4btn[] = { 12, 40, 41, 42, 43, 52, 73, 80, -1 };
|
||||
static int logitech_wheel[] = { 52, 53, 75, 76, 80, 81, 83, 88, 112, -1 };
|
||||
static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
|
||||
76, 80, 81, 83, 88, 96, 97, 112, -1 };
|
||||
static int logitech_mx[] = { 112, -1 };
|
||||
|
||||
//vendor = "Logitech";
|
||||
//DbgPrint("Vendor: %s, name: %s\n", vendor, name);
|
||||
DeviceExtension->model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
|
||||
|
||||
/*if (param[1] < 3)
|
||||
clear_bit(BTN_MIDDLE, DeviceExtension->dev.keybit);
|
||||
if (param[1] < 2)
|
||||
clear_bit(BTN_RIGHT, DeviceExtension->dev.keybit);*/
|
||||
|
||||
DeviceExtension->MouseType = PSMOUSE_PS2;
|
||||
|
||||
for (i = 0; logitech_ps2pp[i] != -1; i++)
|
||||
if (logitech_ps2pp[i] == DeviceExtension->model)
|
||||
DeviceExtension->MouseType = PSMOUSE_PS2PP;
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_PS2PP) {
|
||||
|
||||
/* for (i = 0; logitech_4btn[i] != -1; i++)
|
||||
if (logitech_4btn[i] == psmouse->model)
|
||||
set_bit(BTN_SIDE, psmouse->dev.keybit);
|
||||
*/
|
||||
for (i = 0; logitech_wheel[i] != -1; i++)
|
||||
if (logitech_wheel[i] == DeviceExtension->model) {
|
||||
// set_bit(REL_WHEEL, psmouse->dev.relbit);
|
||||
//name = "Wheel Mouse";DbgPrint("Vendor: %s, name: %s\n", vendor, name);
|
||||
}
|
||||
|
||||
for (i = 0; logitech_mx[i] != -1; i++)
|
||||
if (logitech_mx[i] == DeviceExtension->model) {
|
||||
/* set_bit(BTN_SIDE, psmouse->dev.keybit);
|
||||
set_bit(BTN_EXTRA, psmouse->dev.keybit);
|
||||
set_bit(BTN_BACK, psmouse->dev.keybit);
|
||||
set_bit(BTN_FORWARD, psmouse->dev.keybit);
|
||||
set_bit(BTN_TASK, psmouse->dev.keybit);
|
||||
*/ //name = "MX Mouse";DbgPrint("Vendor: %s, name: %s\n", vendor, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do Logitech PS2++ / PS2T++ magic init.
|
||||
*/
|
||||
|
||||
if (DeviceExtension->model == 97) { /* TouchPad 3 */
|
||||
|
||||
// set_bit(REL_WHEEL, psmouse->dev.relbit);
|
||||
// set_bit(REL_HWHEEL, psmouse->dev.relbit);
|
||||
|
||||
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */
|
||||
psmouse_command(DeviceExtension, param, 0x30d1);
|
||||
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */
|
||||
psmouse_command(DeviceExtension, param, 0x30d1);
|
||||
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */
|
||||
psmouse_command(DeviceExtension, param, 0x30d1);
|
||||
|
||||
param[0] = 0;
|
||||
if (!psmouse_command(DeviceExtension, param, 0x13d1) &&
|
||||
param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) {
|
||||
//name = "TouchPad 3";DbgPrint("Vendor: %s, name: %s\n", vendor, name);
|
||||
return PSMOUSE_PS2TPP;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
param[0] = param[1] = param[2] = 0;
|
||||
ps2pp_cmd(DeviceExtension, param, 0x39); /* Magic knock */
|
||||
ps2pp_cmd(DeviceExtension, param, 0xDB);
|
||||
|
||||
if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 &&
|
||||
(param[2] & 3) == ((param[1] >> 2) & 3)) {
|
||||
ps2pp_set_smartscroll(DeviceExtension);
|
||||
return PSMOUSE_PS2PP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
19
reactos/drivers/input/psaux/logips2pp.h
Normal file
19
reactos/drivers/input/psaux/logips2pp.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Logitech PS/2++ mouse driver header
|
||||
*
|
||||
* Copyright (c) 2003 Vojtech Pavlik <vojtech@suse.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/iotypes.h>
|
||||
#include "psaux.h"
|
||||
|
||||
#ifndef _LOGIPS2PP_H
|
||||
#define _LOGIPS2PP_H
|
||||
void ps2pp_process_packet(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input);
|
||||
void ps2pp_set_800dpi(PDEVICE_EXTENSION DeviceExtension);
|
||||
int ps2pp_detect_model(PDEVICE_EXTENSION DeviceExtension, unsigned char *param);
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.7 2001/08/21 20:13:14 chorns Exp $
|
||||
# $Id: makefile,v 1.8 2003/09/28 00:30:34 weiden Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
|
@ -6,7 +6,7 @@ TARGET_TYPE = driver
|
|||
|
||||
TARGET_NAME = psaux
|
||||
|
||||
TARGET_OBJECTS = $(TARGET_NAME).o controller.o mouse.o
|
||||
TARGET_OBJECTS = $(TARGET_NAME).o controller.o mouse.o logips2pp.o synaptics.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
|
|
|
@ -4,71 +4,85 @@
|
|||
#include "mouse.h"
|
||||
#include "psaux.h"
|
||||
|
||||
typedef BOOLEAN FASTCALL (*PS2MOUSEHANDLER)(PMOUSE_INPUT_DATA Input, PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION DeviceExtension);
|
||||
#define PSMOUSE_LOGITECH_SMARTSCROLL 1
|
||||
|
||||
// Have we got a PS/2 mouse port?
|
||||
static BOOLEAN has_mouse = FALSE;
|
||||
/*
|
||||
* psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
|
||||
* reports relevant events to the input module.
|
||||
*/
|
||||
|
||||
// This points to the function of our mouse handler
|
||||
static PS2MOUSEHANDLER MouseHandler = NULL;
|
||||
|
||||
// This buffer holds the mouse scan codes. The PS/2 protocol sends three characters for each event.
|
||||
static unsigned mouse_buffer[4];
|
||||
|
||||
static int mouse_buffer_position = 0;
|
||||
static int mouse_buffer_size = 3;
|
||||
|
||||
// The number of mouse replies expected
|
||||
static int mouse_replies_expected = 0;
|
||||
|
||||
// Previous button state
|
||||
static ULONG PreviousButtons = 0;
|
||||
|
||||
// Standard PS/2 mouse handler
|
||||
|
||||
BOOLEAN FASTCALL
|
||||
PS2_Standard(PMOUSE_INPUT_DATA Input, PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION DeviceExtension)
|
||||
static void psmouse_process_packet(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input)
|
||||
{
|
||||
ULONG ButtonsDiff;
|
||||
unsigned char *packet = DeviceExtension->MouseBuffer;
|
||||
|
||||
/* Determine the current state of the buttons */
|
||||
Input->RawButtons = (mouse_buffer[0] & 1) /* * GPM_B_LEFT */ |
|
||||
(mouse_buffer[0] & 2) /* * GPM_B_RIGHT */ |
|
||||
(mouse_buffer[0] & 4) /* * GPM_B_MIDDLE */;
|
||||
Input->RawButtons = (packet[0] & 1) ? GPM_B_LEFT : 0;
|
||||
Input->RawButtons |= ((packet[0] >> 1) & 1) ? GPM_B_RIGHT : 0;
|
||||
Input->RawButtons |= ((packet[0] >> 2) & 1) ? GPM_B_MIDDLE : 0;
|
||||
|
||||
/*
|
||||
* The PS2++ protocol is a little bit complex
|
||||
*/
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_PS2PP || DeviceExtension->MouseType == PSMOUSE_PS2TPP)
|
||||
ps2pp_process_packet(DeviceExtension, Input);
|
||||
|
||||
/*
|
||||
* Scroll wheel on IntelliMice, scroll buttons on NetMice
|
||||
*/
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_IMPS || DeviceExtension->MouseType == PSMOUSE_GENPS)
|
||||
{
|
||||
Input->ButtonData = (UINT)((int)((-(signed char) packet[3]) * WHEEL_DELTA));
|
||||
}
|
||||
|
||||
/*
|
||||
* Scroll wheel and buttons on IntelliMouse Explorer
|
||||
*/
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_IMEX)
|
||||
{
|
||||
Input->ButtonData = (UINT)((WHEEL_DELTA) * ((int)(packet[3] & 8) - (int)(packet[3] & 7)));
|
||||
Input->RawButtons |= ((packet[3] >> 4) & 1) ? GPM_B_FOURTH : 0;
|
||||
Input->RawButtons |= ((packet[3] >> 5) & 1) ? GPM_B_FIFTH : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extra buttons on Genius NewNet 3D
|
||||
*/
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_GENPS)
|
||||
{
|
||||
Input->RawButtons |= ((packet[0] >> 6) & 1) ? GPM_B_FOURTH : 0;
|
||||
Input->RawButtons |= ((packet[0] >> 7) & 1) ? GPM_B_FIFTH : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine ButtonFlags
|
||||
*/
|
||||
|
||||
/* Determine ButtonFlags */
|
||||
Input->ButtonFlags = 0;
|
||||
ButtonsDiff = PreviousButtons ^ Input->RawButtons;
|
||||
ButtonsDiff = DeviceExtension->PreviousButtons ^ Input->RawButtons;
|
||||
|
||||
/*
|
||||
* Generic PS/2 Mouse
|
||||
*/
|
||||
|
||||
if(ButtonsDiff & GPM_B_LEFT)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_LEFT)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_1_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_1_UP;
|
||||
}
|
||||
}
|
||||
Input->ButtonFlags |= (Input->RawButtons & GPM_B_LEFT) ? MOUSE_BUTTON_1_DOWN : MOUSE_BUTTON_1_UP;
|
||||
|
||||
if(ButtonsDiff & GPM_B_RIGHT)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_RIGHT)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_2_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_2_UP;
|
||||
}
|
||||
}
|
||||
Input->ButtonFlags |= (Input->RawButtons & GPM_B_RIGHT) ? MOUSE_BUTTON_2_DOWN : MOUSE_BUTTON_2_UP;
|
||||
|
||||
if(ButtonsDiff & GPM_B_MIDDLE)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_MIDDLE)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_3_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_3_UP;
|
||||
}
|
||||
}
|
||||
Input->ButtonFlags |= (Input->RawButtons & GPM_B_MIDDLE) ? MOUSE_BUTTON_3_DOWN : MOUSE_BUTTON_3_UP;
|
||||
|
||||
if(ButtonsDiff & GPM_B_FOURTH)
|
||||
Input->ButtonFlags |= (Input->RawButtons & GPM_B_FOURTH) ? MOUSE_BUTTON_4_DOWN : MOUSE_BUTTON_4_UP;
|
||||
|
||||
if(ButtonsDiff & GPM_B_FIFTH)
|
||||
Input->ButtonFlags |= (Input->RawButtons & GPM_B_FIFTH) ? MOUSE_BUTTON_5_DOWN : MOUSE_BUTTON_5_UP;
|
||||
|
||||
/* Some PS/2 mice send reports with negative bit set in data[0] and zero for
|
||||
* movement. I think this is a bug in the mouse, but working around it only
|
||||
|
@ -77,204 +91,16 @@ PS2_Standard(PMOUSE_INPUT_DATA Input, PDEVICE_OBJECT DeviceObject, PDEVICE_EXTEN
|
|||
* the default of 100 Hz is plenty. (Stephen Tell) */
|
||||
|
||||
/* Determine LastX */
|
||||
if (mouse_buffer[1] == 0)
|
||||
{
|
||||
Input->LastX = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input->LastX = (mouse_buffer[0] & 0x10) ? mouse_buffer[1] - 256
|
||||
: mouse_buffer[1];
|
||||
}
|
||||
Input->LastX = packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0;
|
||||
|
||||
/* Determine LastY */
|
||||
if (mouse_buffer[2] == 0)
|
||||
{
|
||||
Input->LastY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input->LastY = -((mouse_buffer[0] & 0x20) ? mouse_buffer[2] - 256
|
||||
: mouse_buffer[2]);
|
||||
}
|
||||
Input->LastY = packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0;
|
||||
|
||||
/* Copy RawButtons to Previous Buttons for Input */
|
||||
PreviousButtons = Input->RawButtons;
|
||||
DeviceExtension->PreviousButtons = Input->RawButtons;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN FASTCALL
|
||||
PS2_IntelliMouse(PMOUSE_INPUT_DATA Input, PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
ULONG ButtonsDiff;
|
||||
|
||||
/* Determine the current state of the buttons */
|
||||
Input->RawButtons = (mouse_buffer[0] & 1) /* * GPM_B_LEFT */ |
|
||||
(mouse_buffer[0] & 2) /* * GPM_B_RIGHT */ |
|
||||
(mouse_buffer[0] & 4) /* * GPM_B_MIDDLE */;
|
||||
|
||||
/* Determine ButtonFlags */
|
||||
Input->ButtonFlags = 0;
|
||||
ButtonsDiff = PreviousButtons ^ Input->RawButtons;
|
||||
|
||||
if (ButtonsDiff & GPM_B_LEFT)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_LEFT)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_1_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_1_UP;
|
||||
}
|
||||
}
|
||||
|
||||
if (ButtonsDiff & GPM_B_RIGHT)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_RIGHT)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_2_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_2_UP;
|
||||
}
|
||||
}
|
||||
|
||||
if (ButtonsDiff & GPM_B_MIDDLE)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_MIDDLE)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_3_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_3_UP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Some PS/2 mice send reports with negative bit set in data[0] and zero for
|
||||
* movement. I think this is a bug in the mouse, but working around it only
|
||||
* causes artifacts when the actual report is -256; they'll be treated as zero.
|
||||
* This should be rare if the mouse sampling rate is set to a reasonable value;
|
||||
* the default of 100 Hz is plenty. (Stephen Tell) */
|
||||
|
||||
/* Determine LastX */
|
||||
if (mouse_buffer[1] == 0)
|
||||
{
|
||||
Input->LastX = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input->LastX = (mouse_buffer[0] & 0x10) ? mouse_buffer[1] - 256
|
||||
: mouse_buffer[1];
|
||||
}
|
||||
|
||||
/* Determine LastY */
|
||||
if (mouse_buffer[2] == 0)
|
||||
{
|
||||
Input->LastY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input->LastY = -((mouse_buffer[0] & 0x20) ? mouse_buffer[2] - 256
|
||||
: mouse_buffer[2]);
|
||||
}
|
||||
|
||||
/* wheel data */
|
||||
if (mouse_buffer[3])
|
||||
{
|
||||
/* FIXME - store it here? */
|
||||
Input->ExtraInformation = (UINT)mouse_buffer[3];
|
||||
}
|
||||
|
||||
/* Copy RawButtons to Previous Buttons for Input */
|
||||
PreviousButtons = Input->RawButtons;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN FASTCALL
|
||||
PS2_IntelliMouse5Buttons(PMOUSE_INPUT_DATA Input, PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
ULONG ButtonsDiff;
|
||||
|
||||
/* Determine the current state of the buttons */
|
||||
Input->RawButtons = (mouse_buffer[0] & 1) /* * GPM_B_LEFT */ |
|
||||
(mouse_buffer[0] & 2) /* * GPM_B_RIGHT */ |
|
||||
(mouse_buffer[0] & 4) /* * GPM_B_MIDDLE */;
|
||||
|
||||
/* Determine ButtonFlags */
|
||||
Input->ButtonFlags = 0;
|
||||
ButtonsDiff = PreviousButtons ^ Input->RawButtons;
|
||||
|
||||
if (ButtonsDiff & GPM_B_LEFT)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_LEFT)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_1_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_1_UP;
|
||||
}
|
||||
}
|
||||
|
||||
if (ButtonsDiff & GPM_B_RIGHT)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_RIGHT)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_2_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_2_UP;
|
||||
}
|
||||
}
|
||||
|
||||
if (ButtonsDiff & GPM_B_MIDDLE)
|
||||
{
|
||||
if (Input->RawButtons & GPM_B_MIDDLE)
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_3_DOWN;
|
||||
} else {
|
||||
Input->ButtonFlags |= MOUSE_BUTTON_3_UP;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME - get status of XBUTTON1 and XBUTTON2 */
|
||||
|
||||
/* Some PS/2 mice send reports with negative bit set in data[0] and zero for
|
||||
* movement. I think this is a bug in the mouse, but working around it only
|
||||
* causes artifacts when the actual report is -256; they'll be treated as zero.
|
||||
* This should be rare if the mouse sampling rate is set to a reasonable value;
|
||||
* the default of 100 Hz is plenty. (Stephen Tell) */
|
||||
|
||||
/* Determine LastX */
|
||||
if (mouse_buffer[1] == 0)
|
||||
{
|
||||
Input->LastX = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input->LastX = (mouse_buffer[0] & 0x10) ? mouse_buffer[1] - 256
|
||||
: mouse_buffer[1];
|
||||
}
|
||||
|
||||
/* Determine LastY */
|
||||
if (mouse_buffer[2] == 0)
|
||||
{
|
||||
Input->LastY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Input->LastY = -((mouse_buffer[0] & 0x20) ? mouse_buffer[2] - 256
|
||||
: mouse_buffer[2]);
|
||||
}
|
||||
|
||||
/* wheel data */
|
||||
if (mouse_buffer[3])
|
||||
{
|
||||
/* FIXME - store it here? */
|
||||
Input->ExtraInformation = (UINT)mouse_buffer[3];
|
||||
}
|
||||
|
||||
/* Copy RawButtons to Previous Buttons for Input */
|
||||
PreviousButtons = Input->RawButtons;
|
||||
|
||||
return TRUE;
|
||||
if(Input->ButtonData)
|
||||
Input->ButtonFlags |= MOUSE_WHEEL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -287,52 +113,62 @@ ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
|||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PMOUSE_INPUT_DATA Input;
|
||||
ULONG Queue;
|
||||
BOOLEAN ret;
|
||||
BOOLEAN ret = FALSE;
|
||||
int state_dx, state_dy;
|
||||
unsigned scancode;
|
||||
unsigned status = controller_read_status();
|
||||
scancode = controller_read_input();
|
||||
|
||||
if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0)
|
||||
{
|
||||
return FALSE; // keyboard_handle_event(scancode);
|
||||
}
|
||||
|
||||
if(DeviceExtension->acking)
|
||||
{
|
||||
switch(scancode)
|
||||
{
|
||||
case PSMOUSE_RET_ACK:
|
||||
DeviceExtension->ack = 1;
|
||||
break;
|
||||
case PSMOUSE_RET_NAK:
|
||||
DeviceExtension->ack = -1;
|
||||
break;
|
||||
default:
|
||||
DeviceExtension->ack = 1; /* Workaround for mice which don't ACK the Get ID command */
|
||||
if (DeviceExtension->cmdcnt)
|
||||
DeviceExtension->cmdbuf[--DeviceExtension->cmdcnt] = scancode;
|
||||
break;
|
||||
}
|
||||
DeviceExtension->acking = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (DeviceExtension->cmdcnt)
|
||||
{
|
||||
DeviceExtension->cmdbuf[--DeviceExtension->cmdcnt] = scancode;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Don't handle the mouse event if we aren't connected to the mouse class driver */
|
||||
if (DeviceExtension->ClassInformation.CallBack == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
// mouse_handle_event(scancode); proceed to handle it
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE; // keyboard_handle_event(scancode);
|
||||
}
|
||||
|
||||
if (mouse_replies_expected > 0)
|
||||
{
|
||||
if (scancode == MOUSE_ACK)
|
||||
{
|
||||
mouse_replies_expected--;
|
||||
return;
|
||||
}
|
||||
|
||||
mouse_replies_expected = 0;
|
||||
}
|
||||
|
||||
/* Add this scancode to the mouse event queue. */
|
||||
mouse_buffer[mouse_buffer_position] = scancode;
|
||||
mouse_buffer_position++;
|
||||
DeviceExtension->MouseBuffer[DeviceExtension->MouseBufferPosition] = scancode;
|
||||
DeviceExtension->MouseBufferPosition++;
|
||||
|
||||
/* If the buffer is full, parse this event */
|
||||
if (mouse_buffer_position == mouse_buffer_size)
|
||||
{
|
||||
/* Set local variables for DeviceObject and DeviceExtension */
|
||||
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
Queue = DeviceExtension->ActiveQueue % 2;
|
||||
|
||||
/* If the buffer is full, parse the standard ps/2 packets */
|
||||
if (DeviceExtension->MouseBufferPosition ==
|
||||
DeviceExtension->MouseBufferSize + (DeviceExtension->MouseType >= PSMOUSE_GENPS))
|
||||
{
|
||||
|
||||
/* Reset the buffer state. */
|
||||
mouse_buffer_position = 0;
|
||||
DeviceExtension->MouseBufferPosition = 0;
|
||||
|
||||
/* Prevent buffer overflow */
|
||||
if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
|
||||
|
@ -343,42 +179,281 @@ ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
|||
Input = &DeviceExtension->MouseInputData[Queue]
|
||||
[DeviceExtension->InputDataCount[Queue]];
|
||||
|
||||
if(MouseHandler)
|
||||
ret = MouseHandler(Input, DeviceObject, DeviceExtension);
|
||||
else
|
||||
ret = FALSE;
|
||||
psmouse_process_packet(DeviceExtension, Input);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* The synaptics driver has its own resync logic,
|
||||
* so it needs to receive all bytes one at a time.
|
||||
*/
|
||||
if ((DeviceExtension->MouseBufferPosition == 1) && (DeviceExtension->MouseType == PSMOUSE_SYNAPTICS))
|
||||
{
|
||||
// synaptics_process_byte(psmouse, regs);
|
||||
/* Reset the buffer state. */
|
||||
DeviceExtension->MouseBufferPosition = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
if ((DeviceExtension->MouseBufferPosition == 1) && (DeviceExtension->MouseBuffer[0] == PSMOUSE_RET_BAT))
|
||||
{
|
||||
/* FIXME ????????? */
|
||||
DeviceExtension->MouseBufferPosition = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
end:
|
||||
/* Send the Input data to the Mouse Class driver */
|
||||
DeviceExtension->InputDataCount[Queue]++;
|
||||
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a PS/2 mouse command. */
|
||||
/*
|
||||
* psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
|
||||
* It doesn't handle retransmission, though it could - because when there would
|
||||
* be need for retransmissions, the mouse has to be replaced anyway.
|
||||
*/
|
||||
|
||||
static void mouse_write_command (int command)
|
||||
static int psmouse_sendbyte(PDEVICE_EXTENSION DeviceExtension, unsigned char byte)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MODE);
|
||||
controller_wait();
|
||||
controller_write_output (command);
|
||||
}
|
||||
int timeout = 100; /* 100 msec */
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
/* Send a byte to the PS/2 mouse & handle returned ACK. */
|
||||
Millisecond_Timeout.QuadPart = 1;
|
||||
|
||||
DeviceExtension->ack = 0;
|
||||
DeviceExtension->acking = 1;
|
||||
|
||||
static void mouse_write_ack (int value)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_command(CONTROLLER_COMMAND_WRITE_MOUSE);
|
||||
controller_wait();
|
||||
controller_write_output (value);
|
||||
|
||||
/* We expect an ACK in response. */
|
||||
|
||||
mouse_replies_expected++;
|
||||
controller_write_output(byte);
|
||||
controller_wait();
|
||||
while ((DeviceExtension->ack == 0) && timeout--)
|
||||
{
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
return -(DeviceExtension->ack <= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* psmouse_command() sends a command and its parameters to the mouse,
|
||||
* then waits for the response and puts it in the param array.
|
||||
*/
|
||||
|
||||
int psmouse_command(PDEVICE_EXTENSION DeviceExtension, unsigned char *param, int command)
|
||||
{
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
int timeout = 500; /* 500 msec */
|
||||
int send = (command >> 12) & 0xf;
|
||||
int receive = (command >> 8) & 0xf;
|
||||
int i;
|
||||
|
||||
Millisecond_Timeout.QuadPart = 1;
|
||||
|
||||
DeviceExtension->cmdcnt = receive;
|
||||
if (command == PSMOUSE_CMD_RESET_BAT)
|
||||
timeout = 2000; /* 2 sec */
|
||||
|
||||
if (command & 0xff)
|
||||
if (psmouse_sendbyte(DeviceExtension, command & 0xff))
|
||||
return (DeviceExtension->cmdcnt = 0) - 1;
|
||||
|
||||
for (i = 0; i < send; i++)
|
||||
if (psmouse_sendbyte(DeviceExtension, param[i]))
|
||||
return (DeviceExtension->cmdcnt = 0) - 1;
|
||||
|
||||
while (DeviceExtension->cmdcnt && timeout--) {
|
||||
|
||||
if (DeviceExtension->cmdcnt == 1 && command == PSMOUSE_CMD_RESET_BAT)
|
||||
timeout = 100;
|
||||
|
||||
if (DeviceExtension->cmdcnt == 1 && command == PSMOUSE_CMD_GETID &&
|
||||
DeviceExtension->cmdbuf[1] != 0xab && DeviceExtension->cmdbuf[1] != 0xac) {
|
||||
DeviceExtension->cmdcnt = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
|
||||
for (i = 0; i < receive; i++)
|
||||
param[i] = DeviceExtension->cmdbuf[(receive - 1) - i];
|
||||
if (DeviceExtension->cmdcnt)
|
||||
return (DeviceExtension->cmdcnt = 0) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
|
||||
* the mouse may have.
|
||||
*/
|
||||
|
||||
static int psmouse_extensions(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[4];
|
||||
|
||||
param[0] = 0;
|
||||
//vendor = "Generic";
|
||||
//name = "Mouse";
|
||||
DeviceExtension->model = 0;
|
||||
|
||||
if (DeviceExtension->psmouse_noext)
|
||||
{
|
||||
return PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Synaptics TouchPad magic ID
|
||||
*/
|
||||
|
||||
param[0] = 0;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETINFO);
|
||||
|
||||
if (param[1] == 0x47) {
|
||||
//vendor = "Synaptics";
|
||||
//name = "TouchPad";
|
||||
|
||||
if (!synaptics_init(DeviceExtension))
|
||||
return PSMOUSE_SYNAPTICS;
|
||||
else
|
||||
return PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Genius NetMouse magic init.
|
||||
*/
|
||||
|
||||
param[0] = 3;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETINFO);
|
||||
|
||||
if (param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55) {
|
||||
|
||||
//set_bit(BTN_EXTRA, psmouse->dev.keybit);
|
||||
//set_bit(BTN_SIDE, psmouse->dev.keybit);
|
||||
//set_bit(REL_WHEEL, psmouse->dev.relbit);
|
||||
|
||||
//vendor = "Genius";
|
||||
//name = "Wheel Mouse";
|
||||
return PSMOUSE_GENPS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Logitech magic ID.
|
||||
*/
|
||||
|
||||
param[0] = 0;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
param[1] = 0;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETINFO);
|
||||
|
||||
if (param[1]) {
|
||||
int type = ps2pp_detect_model(DeviceExtension, param);
|
||||
if (type)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try IntelliMouse magic init.
|
||||
*/
|
||||
|
||||
param[0] = 200;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 100;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 80;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETID);
|
||||
|
||||
if (param[0] == 3) {
|
||||
|
||||
// set_bit(REL_WHEEL, DeviceExtension->dev.relbit);
|
||||
|
||||
/*
|
||||
* Try IntelliMouse/Explorer magic init.
|
||||
*/
|
||||
|
||||
param[0] = 200;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 200;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 80;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETID);
|
||||
|
||||
if (param[0] == 4) {
|
||||
|
||||
//set_bit(BTN_SIDE, psmouse->dev.keybit);
|
||||
//set_bit(BTN_EXTRA, psmouse->dev.keybit);
|
||||
|
||||
//name = "Explorer Mouse";
|
||||
return PSMOUSE_IMEX;
|
||||
}
|
||||
|
||||
//name = "Wheel Mouse";
|
||||
return PSMOUSE_IMPS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay, all failed, we have a standard mouse here. The number of the buttons
|
||||
* is still a question, though. We assume 3.
|
||||
*/
|
||||
return PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
/*
|
||||
* psmouse_test() probes for a PS/2 mouse.
|
||||
*/
|
||||
|
||||
static int psmouse_test(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[2];
|
||||
/*
|
||||
* First, we check if it's a mouse. It should send 0x00 or 0x03
|
||||
* in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer.
|
||||
*/
|
||||
|
||||
param[0] = param[1] = 0xa5;
|
||||
|
||||
if (psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETID))
|
||||
return -1;
|
||||
|
||||
if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Then we reset and disable the mouse so that it doesn't generate events.
|
||||
*/
|
||||
|
||||
if (psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_RESET_DIS))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* And here we try to determine if it has any extensions over the
|
||||
* basic PS/2 3-button mouse.
|
||||
*/
|
||||
return DeviceExtension->MouseType = psmouse_extensions(DeviceExtension);
|
||||
}
|
||||
|
||||
/* Check if this is a dual port controller. */
|
||||
|
@ -426,133 +501,109 @@ BOOLEAN detect_ps2_port(void)
|
|||
return return_value;
|
||||
}
|
||||
|
||||
// Initialize the PS/2 mouse support
|
||||
/*
|
||||
* Here we set the mouse resolution.
|
||||
*/
|
||||
|
||||
static void psmouse_set_resolution(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[1];
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_PS2PP && DeviceExtension->Resolution > 400) {
|
||||
ps2pp_set_800dpi(DeviceExtension);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DeviceExtension->Resolution || DeviceExtension->Resolution >= 200)
|
||||
param[0] = 3;
|
||||
else if (DeviceExtension->Resolution >= 100)
|
||||
param[0] = 2;
|
||||
else if (DeviceExtension->Resolution >= 50)
|
||||
param[0] = 1;
|
||||
else if (DeviceExtension->Resolution)
|
||||
param[0] = 0;
|
||||
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
}
|
||||
|
||||
/*
|
||||
* psmouse_initialize() initializes the mouse to a sane state.
|
||||
*/
|
||||
|
||||
static void psmouse_initialize(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[2];
|
||||
/*
|
||||
* We set the mouse report rate to a highest possible value.
|
||||
* We try 100 first in case mouse fails to set 200.
|
||||
*/
|
||||
|
||||
param[0] = 100;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
|
||||
param[0] = 200;
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
|
||||
/*
|
||||
* We also set the resolution and scaling.
|
||||
*/
|
||||
|
||||
psmouse_set_resolution(DeviceExtension);
|
||||
psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
|
||||
/*
|
||||
* We set the mouse into streaming mode.
|
||||
*/
|
||||
|
||||
psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETSTREAM);
|
||||
|
||||
/*
|
||||
* Last, we enable the mouse so that we get reports from it.
|
||||
*/
|
||||
|
||||
if (psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_ENABLE))
|
||||
DbgPrint("mouse.c: Failed to enable mouse\n");
|
||||
}
|
||||
|
||||
/* Initialize the PS/2 mouse support */
|
||||
BOOLEAN mouse_init (PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
BOOL ScanIntelli = TRUE, ScanIntelli5Btns = TRUE;
|
||||
unsigned scancode;
|
||||
unsigned char status;
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
if (!detect_ps2_port ()) return FALSE;
|
||||
DeviceExtension->MouseBufferPosition = 0;
|
||||
DeviceExtension->MouseBufferSize = 3; /* standard PS/2 packet size */
|
||||
DeviceExtension->PreviousButtons = 0;
|
||||
DeviceExtension->MouseType = 0;
|
||||
|
||||
Millisecond_Timeout.QuadPart = 1;
|
||||
|
||||
has_mouse = TRUE;
|
||||
MouseHandler = PS2_Standard;
|
||||
DeviceExtension->psmouse_noext = 0; // Set this to 1 if you don't want to detect enhanced mice
|
||||
DeviceExtension->psmouse_smartscroll = PSMOUSE_LOGITECH_SMARTSCROLL;
|
||||
DeviceExtension->Resolution = 600; // Set this to the resolution of the mouse
|
||||
|
||||
DeviceExtension->InputDataCount[0] = 0;
|
||||
DeviceExtension->InputDataCount[1] = 0;
|
||||
DeviceExtension->ActiveQueue = 0;
|
||||
|
||||
DeviceExtension->ack = 0;
|
||||
DeviceExtension->acking = 0;
|
||||
|
||||
DeviceExtension->HasMouse = detect_ps2_port();
|
||||
|
||||
if(!DeviceExtension->HasMouse)
|
||||
return FALSE;
|
||||
|
||||
// Enable the PS/2 mouse port
|
||||
controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE);
|
||||
|
||||
// Attempt to enter ms scrolling mouse mode
|
||||
|
||||
init:
|
||||
|
||||
// 200 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (200);
|
||||
|
||||
if(ScanIntelli)
|
||||
{
|
||||
|
||||
// 100 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (100);
|
||||
|
||||
// 80 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (80);
|
||||
|
||||
// let's test if it's a ms scrolling mouse
|
||||
mouse_write_ack (MOUSE_READ_DEVICETYPE);
|
||||
|
||||
/* check if it is a ms intellimouse */
|
||||
scancode = controller_read_input();
|
||||
switch(scancode)
|
||||
{
|
||||
case MOUSE_ISINTELLIMOUSE:
|
||||
/* detected a ms intellimouse with a mouse wheel */
|
||||
mouse_buffer_size = 4;
|
||||
MouseHandler = PS2_IntelliMouse;
|
||||
|
||||
if(!ScanIntelli5Btns)
|
||||
break;
|
||||
|
||||
/* FIXME - do we ever get here? see
|
||||
http://perso.wanadoo.es/juanramon.villodas/PS-2%20Mouse%20Interfacing.htm
|
||||
|
||||
*/
|
||||
|
||||
/* let's check if the mouse has 5 buttons */
|
||||
// 200 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (200);
|
||||
|
||||
// 100 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (200);
|
||||
|
||||
// 80 samples/sec
|
||||
mouse_write_ack (MOUSE_SET_SAMPLE_RATE);
|
||||
mouse_write_ack (80);
|
||||
|
||||
// let's test if it's a ms scrolling mouse with 5 buttons
|
||||
mouse_write_ack (MOUSE_READ_DEVICETYPE);
|
||||
|
||||
scancode = controller_read_input();
|
||||
if(scancode == MOUSE_ISINTELLIMOUSE5BUTTONS)
|
||||
{
|
||||
/* detected a ms intellimouse with 5 mouse buttons */
|
||||
mouse_buffer_size = 4;
|
||||
MouseHandler = PS2_IntelliMouse5Buttons;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the mouse doesn't have 5 buttons, reset and init the standard intellimouse */
|
||||
mouse_write_ack (MOUSE_RESET);
|
||||
ScanIntelli5Btns = FALSE;
|
||||
goto init;
|
||||
}
|
||||
break;
|
||||
|
||||
/* FIXME - does this ever happen or did i just misunderstood something? */
|
||||
case MOUSE_ISINTELLIMOUSE5BUTTONS:
|
||||
/* detected a ms intellimouse with a mouse wheel */
|
||||
mouse_buffer_size = 4;
|
||||
MouseHandler = PS2_IntelliMouse5Buttons;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* this is a standard ps/2 mouse only, reset and init it again */
|
||||
mouse_write_ack (MOUSE_RESET);
|
||||
ScanIntelli = FALSE;
|
||||
goto init;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 8 counts per mm
|
||||
mouse_write_ack (MOUSE_SET_RESOLUTION);
|
||||
mouse_write_ack (3);
|
||||
|
||||
// 2:1 scaling
|
||||
mouse_write_ack (MOUSE_SET_SCALE21);
|
||||
|
||||
// Enable the PS/2 device
|
||||
mouse_write_ack (MOUSE_ENABLE_DEVICE);
|
||||
|
||||
// Enable controller interrupts
|
||||
mouse_write_command (MOUSE_INTERRUPTS_ON);
|
||||
controller_wait();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MODE);
|
||||
controller_wait();
|
||||
controller_write_output (MOUSE_INTERRUPTS_ON);
|
||||
controller_wait();
|
||||
|
||||
// Connect the interrupt for the mouse irq
|
||||
MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, &Dirql, &Affinity);
|
||||
|
@ -560,5 +611,9 @@ init:
|
|||
IoConnectInterrupt(&DeviceExtension->MouseInterrupt, ps2_mouse_handler, DeviceObject, NULL, MappedIrq,
|
||||
Dirql, Dirql, 0, FALSE, Affinity, FALSE);
|
||||
|
||||
psmouse_test(DeviceExtension);
|
||||
psmouse_initialize(DeviceExtension);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,35 @@
|
|||
#define MOUSE_ISINTELLIMOUSE 0x03
|
||||
#define MOUSE_ISINTELLIMOUSE5BUTTONS 0x04
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define WHEEL_DELTA 120
|
||||
|
||||
#define PSMOUSE_CMD_SETSCALE11 0x00e6
|
||||
#define PSMOUSE_CMD_SETRES 0x10e8
|
||||
#define PSMOUSE_CMD_GETINFO 0x03e9
|
||||
#define PSMOUSE_CMD_SETSTREAM 0x00ea
|
||||
#define PSMOUSE_CMD_POLL 0x03eb
|
||||
#define PSMOUSE_CMD_GETID 0x02f2
|
||||
#define PSMOUSE_CMD_SETRATE 0x10f3
|
||||
#define PSMOUSE_CMD_ENABLE 0x00f4
|
||||
#define PSMOUSE_CMD_RESET_DIS 0x00f6
|
||||
#define PSMOUSE_CMD_RESET_BAT 0x02ff
|
||||
|
||||
#define PSMOUSE_RET_BAT 0xaa
|
||||
#define PSMOUSE_RET_ACK 0xfa
|
||||
#define PSMOUSE_RET_NAK 0xfe
|
||||
|
||||
#define PSMOUSE_PS2 1
|
||||
#define PSMOUSE_PS2PP 2
|
||||
#define PSMOUSE_PS2TPP 3
|
||||
#define PSMOUSE_GENPS 4
|
||||
#define PSMOUSE_IMPS 5
|
||||
#define PSMOUSE_IMEX 6
|
||||
#define PSMOUSE_SYNAPTICS 7
|
||||
|
||||
#define input_regs(a,b) do { (a)->regs = (b); } while (0)
|
||||
|
||||
static PIRP CurrentIrp;
|
||||
static ULONG MouseDataRead;
|
||||
static ULONG MouseDataRequired;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <ddk/ntddk.h>
|
||||
#include <ddk/iotypes.h>
|
||||
typedef struct _DEVICE_EXTENSION {
|
||||
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
@ -5,10 +7,29 @@ typedef struct _DEVICE_EXTENSION {
|
|||
ULONG ActiveQueue;
|
||||
ULONG InputDataCount[2];
|
||||
MOUSE_INPUT_DATA MouseInputData[2][MOUSE_BUFFER_SIZE];
|
||||
BOOL HasMouse;
|
||||
|
||||
unsigned char MouseType;
|
||||
unsigned char model;
|
||||
|
||||
unsigned char MouseBuffer[8];
|
||||
UINT MouseBufferPosition;
|
||||
UINT MouseBufferSize;
|
||||
UINT Resolution;
|
||||
|
||||
unsigned char cmdbuf[8];
|
||||
unsigned char cmdcnt;
|
||||
unsigned char pktcnt;
|
||||
char acking;
|
||||
volatile char ack;
|
||||
|
||||
int psmouse_noext;
|
||||
int psmouse_smartscroll;
|
||||
|
||||
ULONG PreviousButtons;
|
||||
|
||||
CLASS_INFORMATION ClassInformation;
|
||||
|
||||
PKINTERRUPT MouseInterrupt;
|
||||
KDPC IsrDpc;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
|
|
410
reactos/drivers/input/psaux/synaptics.c
Normal file
410
reactos/drivers/input/psaux/synaptics.c
Normal file
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* Synaptics TouchPad PS/2 mouse driver
|
||||
*
|
||||
* 2003 Peter Osterlund <petero2@telia.com>
|
||||
* Ported to 2.5 input device infrastructure.
|
||||
*
|
||||
* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
|
||||
* start merging tpconfig and gpm code to a xfree-input module
|
||||
* adding some changes and extensions (ex. 3rd and 4th button)
|
||||
*
|
||||
* Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
|
||||
* Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
|
||||
* code for the special synaptics commands (from the tpconfig-source)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* Trademarks are the property of their respective owners.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define NO_SYNAPTICS
|
||||
|
||||
|
||||
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/ntddmou.h>
|
||||
#include <ddk/iotypes.h>
|
||||
#include "mouse.h"
|
||||
#include "psaux.h"
|
||||
|
||||
#ifndef NO_SYNAPTICS
|
||||
|
||||
#include "synaptics.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Synaptics communications functions
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Use the Synaptics extended ps/2 syntax to write a special command byte.
|
||||
* special command: 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
|
||||
* is the command. A 0xF3 or 0xE9 must follow (see synaptics_send_cmd
|
||||
* and synaptics_set_mode)
|
||||
*/
|
||||
static int synaptics_special_cmd(PDEVICE_EXTENSION DeviceExtension, unsigned char command)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (psmouse_command(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11))
|
||||
return -1;
|
||||
|
||||
for (i = 6; i >= 0; i -= 2) {
|
||||
unsigned char d = (command >> i) & 3;
|
||||
if (psmouse_command(DeviceExtension, &d, PSMOUSE_CMD_SETRES))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to the synpatics touchpad by special commands
|
||||
*/
|
||||
static int synaptics_send_cmd(PDEVICE_EXTENSION DeviceExtension, unsigned char c, unsigned char *param)
|
||||
{
|
||||
if (synaptics_special_cmd(DeviceExtension, c))
|
||||
return -1;
|
||||
if (psmouse_command(DeviceExtension, param, PSMOUSE_CMD_GETINFO))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the synaptics touchpad mode byte by special commands
|
||||
*/
|
||||
static int synaptics_set_mode(PDEVICE_EXTENSION DeviceExtension, unsigned char mode)
|
||||
{
|
||||
unsigned char param[1];
|
||||
|
||||
if (synaptics_special_cmd(DeviceExtension, mode))
|
||||
return -1;
|
||||
param[0] = 0x14;
|
||||
if (psmouse_command(DeviceExtension, param, PSMOUSE_CMD_SETRATE))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int synaptics_reset(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char r[2];
|
||||
|
||||
if (psmouse_command(DeviceExtension, r, PSMOUSE_CMD_RESET_BAT))
|
||||
return -1;
|
||||
if (r[0] == 0xAA && r[1] == 0x00)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the model-id bytes from the touchpad
|
||||
* see also SYN_MODEL_* macros
|
||||
*/
|
||||
static int synaptics_model_id(struct psmouse *psmouse, unsigned long int *model_id)
|
||||
{
|
||||
unsigned char mi[3];
|
||||
|
||||
if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi))
|
||||
return -1;
|
||||
*model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the capability-bits from the touchpad
|
||||
* see also the SYN_CAP_* macros
|
||||
*/
|
||||
static int synaptics_capability(struct psmouse *psmouse, unsigned long int *capability)
|
||||
{
|
||||
unsigned char cap[3];
|
||||
|
||||
if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
|
||||
return -1;
|
||||
*capability = (cap[0]<<16) | (cap[1]<<8) | cap[2];
|
||||
if (SYN_CAP_VALID(*capability))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identify Touchpad
|
||||
* See also the SYN_ID_* macros
|
||||
*/
|
||||
static int synaptics_identify(struct psmouse *psmouse, unsigned long int *ident)
|
||||
{
|
||||
unsigned char id[3];
|
||||
|
||||
if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id))
|
||||
return -1;
|
||||
*ident = (id[0]<<16) | (id[1]<<8) | id[2];
|
||||
if (SYN_ID_IS_SYNAPTICS(*ident))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int synaptics_enable_device(struct psmouse *psmouse)
|
||||
{
|
||||
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_ident(struct synaptics_data *priv)
|
||||
{
|
||||
printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity));
|
||||
printk(KERN_INFO " Firware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity),
|
||||
SYN_ID_MINOR(priv->identity));
|
||||
|
||||
if (SYN_MODEL_ROT180(priv->model_id))
|
||||
printk(KERN_INFO " 180 degree mounted touchpad\n");
|
||||
if (SYN_MODEL_PORTRAIT(priv->model_id))
|
||||
printk(KERN_INFO " portrait touchpad\n");
|
||||
printk(KERN_INFO " Sensor: %ld\n", SYN_MODEL_SENSOR(priv->model_id));
|
||||
if (SYN_MODEL_NEWABS(priv->model_id))
|
||||
printk(KERN_INFO " new absolute packet format\n");
|
||||
if (SYN_MODEL_PEN(priv->model_id))
|
||||
printk(KERN_INFO " pen detection\n");
|
||||
|
||||
if (SYN_CAP_EXTENDED(priv->capabilities)) {
|
||||
printk(KERN_INFO " Touchpad has extended capability bits\n");
|
||||
if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
|
||||
printk(KERN_INFO " -> four buttons\n");
|
||||
if (SYN_CAP_MULTIFINGER(priv->capabilities))
|
||||
printk(KERN_INFO " -> multifinger detection\n");
|
||||
if (SYN_CAP_PALMDETECT(priv->capabilities))
|
||||
printk(KERN_INFO " -> palm detection\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int query_hardware(struct psmouse *psmouse)
|
||||
{
|
||||
struct synaptics_data *priv = psmouse->private;
|
||||
int retries = 0;
|
||||
|
||||
while ((retries++ < 3) && synaptics_reset(psmouse))
|
||||
printk(KERN_ERR "synaptics reset failed\n");
|
||||
|
||||
if (synaptics_identify(psmouse, &priv->identity))
|
||||
return -1;
|
||||
if (synaptics_model_id(psmouse, &priv->model_id))
|
||||
return -1;
|
||||
if (synaptics_capability(psmouse, &priv->capabilities))
|
||||
return -1;
|
||||
if (synaptics_set_mode(psmouse, (SYN_BIT_ABSOLUTE_MODE |
|
||||
SYN_BIT_HIGH_RATE |
|
||||
SYN_BIT_DISABLE_GESTURE |
|
||||
SYN_BIT_W_MODE)))
|
||||
return -1;
|
||||
|
||||
synaptics_enable_device(psmouse);
|
||||
|
||||
print_ident(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Driver initialization/cleanup functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline void set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
|
||||
{
|
||||
dev->absmin[axis] = min;
|
||||
dev->absmax[axis] = max;
|
||||
dev->absfuzz[axis] = fuzz;
|
||||
dev->absflat[axis] = flat;
|
||||
|
||||
set_bit(axis, dev->absbit);
|
||||
}
|
||||
|
||||
int synaptics_init(struct psmouse *psmouse)
|
||||
{
|
||||
struct synaptics_data *priv;
|
||||
|
||||
psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -1;
|
||||
memset(priv, 0, sizeof(struct synaptics_data));
|
||||
|
||||
priv->inSync = 1;
|
||||
|
||||
if (query_hardware(psmouse)) {
|
||||
printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n");
|
||||
goto init_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
|
||||
* which says that they should be valid regardless of the actual size of
|
||||
* the senser.
|
||||
*/
|
||||
set_bit(EV_ABS, psmouse->dev.evbit);
|
||||
set_abs_params(&psmouse->dev, ABS_X, 1472, 5472, 0, 0);
|
||||
set_abs_params(&psmouse->dev, ABS_Y, 1408, 4448, 0, 0);
|
||||
set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 255, 0, 0);
|
||||
|
||||
set_bit(EV_MSC, psmouse->dev.evbit);
|
||||
set_bit(MSC_GESTURE, psmouse->dev.mscbit);
|
||||
|
||||
set_bit(EV_KEY, psmouse->dev.evbit);
|
||||
set_bit(BTN_LEFT, psmouse->dev.keybit);
|
||||
set_bit(BTN_RIGHT, psmouse->dev.keybit);
|
||||
set_bit(BTN_FORWARD, psmouse->dev.keybit);
|
||||
set_bit(BTN_BACK, psmouse->dev.keybit);
|
||||
|
||||
clear_bit(EV_REL, psmouse->dev.evbit);
|
||||
clear_bit(REL_X, psmouse->dev.relbit);
|
||||
clear_bit(REL_Y, psmouse->dev.relbit);
|
||||
|
||||
return 0;
|
||||
|
||||
init_fail:
|
||||
kfree(priv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void synaptics_disconnect(struct psmouse *psmouse)
|
||||
{
|
||||
struct synaptics_data *priv = psmouse->private;
|
||||
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Functions to interpret the absolute mode packets
|
||||
****************************************************************************/
|
||||
|
||||
static void synaptics_parse_hw_state(struct synaptics_data *priv, struct synaptics_hw_state *hw)
|
||||
{
|
||||
unsigned char *buf = priv->proto_buf;
|
||||
|
||||
hw->x = (((buf[3] & 0x10) << 8) |
|
||||
((buf[1] & 0x0f) << 8) |
|
||||
buf[4]);
|
||||
hw->y = (((buf[3] & 0x20) << 7) |
|
||||
((buf[1] & 0xf0) << 4) |
|
||||
buf[5]);
|
||||
|
||||
hw->z = buf[2];
|
||||
hw->w = (((buf[0] & 0x30) >> 2) |
|
||||
((buf[0] & 0x04) >> 1) |
|
||||
((buf[3] & 0x04) >> 2));
|
||||
|
||||
hw->left = (buf[0] & 0x01) ? 1 : 0;
|
||||
hw->right = (buf[0] & 0x2) ? 1 : 0;
|
||||
hw->up = 0;
|
||||
hw->down = 0;
|
||||
|
||||
if (SYN_CAP_EXTENDED(priv->capabilities) &&
|
||||
(SYN_CAP_FOUR_BUTTON(priv->capabilities))) {
|
||||
hw->up = ((buf[3] & 0x01)) ? 1 : 0;
|
||||
if (hw->left)
|
||||
hw->up = !hw->up;
|
||||
hw->down = ((buf[3] & 0x02)) ? 1 : 0;
|
||||
if (hw->right)
|
||||
hw->down = !hw->down;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called for each full received packet from the touchpad
|
||||
*/
|
||||
static void synaptics_process_packet(struct psmouse *psmouse)
|
||||
{
|
||||
struct input_dev *dev = &psmouse->dev;
|
||||
struct synaptics_data *priv = psmouse->private;
|
||||
struct synaptics_hw_state hw;
|
||||
|
||||
synaptics_parse_hw_state(priv, &hw);
|
||||
|
||||
if (hw.z > 0) {
|
||||
int w_ok = 0;
|
||||
/*
|
||||
* Use capability bits to decide if the w value is valid.
|
||||
* If not, set it to 5, which corresponds to a finger of
|
||||
* normal width.
|
||||
*/
|
||||
if (SYN_CAP_EXTENDED(priv->capabilities)) {
|
||||
switch (hw.w) {
|
||||
case 0 ... 1:
|
||||
w_ok = SYN_CAP_MULTIFINGER(priv->capabilities);
|
||||
break;
|
||||
case 2:
|
||||
w_ok = SYN_MODEL_PEN(priv->model_id);
|
||||
break;
|
||||
case 4 ... 15:
|
||||
w_ok = SYN_CAP_PALMDETECT(priv->capabilities);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!w_ok)
|
||||
hw.w = 5;
|
||||
}
|
||||
|
||||
/* Post events */
|
||||
input_report_abs(dev, ABS_X, hw.x);
|
||||
input_report_abs(dev, ABS_Y, hw.y);
|
||||
input_report_abs(dev, ABS_PRESSURE, hw.z);
|
||||
|
||||
if (hw.w != priv->old_w) {
|
||||
input_event(dev, EV_MSC, MSC_GESTURE, hw.w);
|
||||
priv->old_w = hw.w;
|
||||
}
|
||||
|
||||
input_report_key(dev, BTN_LEFT, hw.left);
|
||||
input_report_key(dev, BTN_RIGHT, hw.right);
|
||||
input_report_key(dev, BTN_FORWARD, hw.up);
|
||||
input_report_key(dev, BTN_BACK, hw.down);
|
||||
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
|
||||
{
|
||||
struct input_dev *dev = &psmouse->dev;
|
||||
struct synaptics_data *priv = psmouse->private;
|
||||
unsigned char *pBuf = priv->proto_buf;
|
||||
unsigned char u = psmouse->packet[0];
|
||||
|
||||
input_regs(dev, regs);
|
||||
|
||||
pBuf[priv->proto_buf_tail++] = u;
|
||||
|
||||
/* check first byte */
|
||||
if ((priv->proto_buf_tail == 1) && ((u & 0xC8) != 0x80)) {
|
||||
priv->inSync = 0;
|
||||
priv->proto_buf_tail = 0;
|
||||
printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* check 4th byte */
|
||||
if ((priv->proto_buf_tail == 4) && ((u & 0xc8) != 0xc0)) {
|
||||
priv->inSync = 0;
|
||||
priv->proto_buf_tail = 0;
|
||||
printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->proto_buf_tail >= 6) { /* Full packet received */
|
||||
if (!priv->inSync) {
|
||||
priv->inSync = 1;
|
||||
printk(KERN_NOTICE "Synaptics driver resynced.\n");
|
||||
}
|
||||
synaptics_process_packet(psmouse);
|
||||
priv->proto_buf_tail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int synaptics_init(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
100
reactos/drivers/input/psaux/synaptics.h
Normal file
100
reactos/drivers/input/psaux/synaptics.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Synaptics TouchPad PS/2 mouse driver
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#ifndef NO_SYNAPTICS
|
||||
|
||||
#ifndef _SYNAPTICS_H
|
||||
#define _SYNAPTICS_H
|
||||
|
||||
extern void synaptics_process_byte(DeviceExtension, struct pt_regs *regs);
|
||||
#endif
|
||||
extern int synaptics_init(DeviceExtension);
|
||||
#ifndef NO_SYNAPTICS
|
||||
extern void synaptics_disconnect(DeviceExtension);
|
||||
|
||||
/* synaptics queries */
|
||||
#define SYN_QUE_IDENTIFY 0x00
|
||||
#define SYN_QUE_MODES 0x01
|
||||
#define SYN_QUE_CAPABILITIES 0x02
|
||||
#define SYN_QUE_MODEL 0x03
|
||||
#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
|
||||
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
|
||||
#define SYN_QUE_RESOLUTION 0x08
|
||||
|
||||
/* synatics modes */
|
||||
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
|
||||
#define SYN_BIT_HIGH_RATE (1 << 6)
|
||||
#define SYN_BIT_SLEEP_MODE (1 << 3)
|
||||
#define SYN_BIT_DISABLE_GESTURE (1 << 2)
|
||||
#define SYN_BIT_W_MODE (1 << 0)
|
||||
|
||||
/* synaptics model ID bits */
|
||||
#define SYN_MODEL_ROT180(m) ((m) & (1 << 23))
|
||||
#define SYN_MODEL_PORTRAIT(m) ((m) & (1 << 22))
|
||||
#define SYN_MODEL_SENSOR(m) (((m) >> 16) & 0x3f)
|
||||
#define SYN_MODEL_HARDWARE(m) (((m) >> 9) & 0x7f)
|
||||
#define SYN_MODEL_NEWABS(m) ((m) & (1 << 7))
|
||||
#define SYN_MODEL_PEN(m) ((m) & (1 << 6))
|
||||
#define SYN_MODEL_SIMPLIC(m) ((m) & (1 << 5))
|
||||
#define SYN_MODEL_GEOMETRY(m) ((m) & 0x0f)
|
||||
|
||||
/* synaptics capability bits */
|
||||
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
|
||||
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
|
||||
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
|
||||
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
|
||||
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
|
||||
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
|
||||
|
||||
/* synaptics modes query bits */
|
||||
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
|
||||
#define SYN_MODE_RATE(m) ((m) & (1 << 6))
|
||||
#define SYN_MODE_BAUD_SLEEP(m) ((m) & (1 << 3))
|
||||
#define SYN_MODE_DISABLE_GESTURE(m) ((m) & (1 << 2))
|
||||
#define SYN_MODE_PACKSIZE(m) ((m) & (1 << 1))
|
||||
#define SYN_MODE_WMODE(m) ((m) & (1 << 0))
|
||||
|
||||
/* synaptics identify query bits */
|
||||
#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f)
|
||||
#define SYN_ID_MAJOR(i) ((i) & 0x0f)
|
||||
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
|
||||
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
|
||||
|
||||
/*
|
||||
* A structure to describe the state of the touchpad hardware (buttons and pad)
|
||||
*/
|
||||
|
||||
struct synaptics_hw_state {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int w;
|
||||
int left;
|
||||
int right;
|
||||
int up;
|
||||
int down;
|
||||
};
|
||||
|
||||
struct synaptics_data {
|
||||
/* Data read from the touchpad */
|
||||
unsigned long int model_id; /* Model-ID */
|
||||
unsigned long int capabilities; /* Capabilities */
|
||||
unsigned long int identity; /* Identification */
|
||||
|
||||
/* Data for normal processing */
|
||||
unsigned char proto_buf[6]; /* Buffer for Packet */
|
||||
unsigned char last_byte; /* last received byte */
|
||||
int inSync; /* Packets in sync */
|
||||
int proto_buf_tail;
|
||||
|
||||
int old_w; /* Previous w value */
|
||||
};
|
||||
|
||||
#endif /* _SYNAPTICS_H */
|
||||
|
||||
#endif /* NO_SYNAPTICS */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue