mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Byebye decrepit drivers
svn path=/trunk/; revision=14938
This commit is contained in:
parent
24f249ab54
commit
b099687f31
19 changed files with 2 additions and 3177 deletions
|
@ -84,7 +84,7 @@ DRIVERS_LIB = bzip2 oskittcp ip csq
|
|||
DEVICE_DRIVERS = beep blue debugout null serial bootvid
|
||||
|
||||
# Kernel mode input drivers
|
||||
INPUT_DRIVERS = keyboard mouclass psaux sermouse i8042prt kbdclass
|
||||
INPUT_DRIVERS = mouclass sermouse i8042prt kbdclass
|
||||
|
||||
# Kernel mode file system drivers
|
||||
# cdfs ext2 fs_rec ms np vfat
|
||||
|
|
|
@ -6,7 +6,7 @@ PATH_TO_TOP = ../..
|
|||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
DRIVERS = keyboard mouclass psaux sermouse i8042prt kbdclass
|
||||
DRIVERS = mouclass sermouse i8042prt kbdclass
|
||||
|
||||
all: $(DRIVERS)
|
||||
|
||||
|
|
|
@ -1,907 +0,0 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/dd/keyboard/keyboard.c
|
||||
* PURPOSE: Keyboard driver
|
||||
* PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
|
||||
* Jason Filby (jasonfilby@yahoo.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <string.h>
|
||||
#include <ntos/keyboard.h>
|
||||
#include <ntos/minmax.h>
|
||||
#include <rosrtl/string.h>
|
||||
|
||||
#include <ddk/ntddkbd.h>
|
||||
#include <ddk/ntdd8042.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "keyboard.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
/*
|
||||
* Driver data
|
||||
*/
|
||||
|
||||
static KEY_EVENT_RECORD kbdBuffer[KBD_BUFFER_SIZE];
|
||||
static int bufHead,bufTail;
|
||||
static int keysInBuffer;
|
||||
static int extKey;
|
||||
static BYTE ledStatus;
|
||||
static BYTE capsDown,numDown,scrollDown;
|
||||
static DWORD ctrlKeyState;
|
||||
static PKINTERRUPT KbdInterrupt;
|
||||
static KDPC KbdDpc;
|
||||
static PIO_WORKITEM KbdWorkItem = NULL;
|
||||
static BOOLEAN AlreadyOpened = FALSE;
|
||||
|
||||
/*
|
||||
* PURPOSE: Current irp being processed
|
||||
*/
|
||||
static PIRP CurrentIrp;
|
||||
|
||||
/*
|
||||
* PURPOSE: Number of keys that have been read into the current irp's buffer
|
||||
*/
|
||||
static ULONG KeysRead;
|
||||
static ULONG KeysRequired;
|
||||
|
||||
/*
|
||||
* Virtual key codes table
|
||||
*
|
||||
* Comments:
|
||||
* * PrtSc = VK_PRINT
|
||||
* * Alt+PrtSc (SysRq) = VK_EXECUTE
|
||||
* * Alt = VK_MENU
|
||||
*/
|
||||
|
||||
static const WORD vkTable[128]=
|
||||
{
|
||||
/* 00 - 07 */ 0, VK_ESCAPE, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6,
|
||||
/* 08 - 0F */ VK_7, VK_8, VK_9, VK_0, 189, 187, VK_BACK, VK_TAB,
|
||||
/* 10 - 17 */ VK_Q, VK_W, VK_E, VK_R, VK_T, VK_Y, VK_U, VK_I,
|
||||
/* 18 - 1F */ VK_O, VK_P, 219, 221, VK_RETURN, VK_CONTROL, VK_A, VK_S,
|
||||
/* 20 - 27 */ VK_D, VK_F, VK_G, VK_H, VK_J, VK_K, VK_L, 186,
|
||||
/* 28 - 2F */ 222, 192, VK_SHIFT, 220, VK_Z, VK_X, VK_C, VK_V,
|
||||
/* 30 - 37 */ VK_B, VK_N, VK_M, 188, 190, 191, VK_SHIFT, VK_MULTIPLY,
|
||||
/* 38 - 3F */ VK_MENU, VK_SPACE, VK_CAPITAL, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
|
||||
/* 40 - 47 */ VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME,
|
||||
/* 48 - 4F */ VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_ADD, VK_END,
|
||||
/* 50 - 57 */ VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE, VK_EXECUTE, 0, 0, VK_F11,
|
||||
/* 58 - 5F */ VK_F12, 0, 0, 91, 92, 93, 0, 0,
|
||||
/* 60 - 67 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 68 - 6F */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 70 - 77 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 78 - 7F */ 0, 0, 0, 0, 0, 0, 0, VK_PAUSE
|
||||
};
|
||||
static const WORD vkKeypadTable[13]= /* 47 - 53 */
|
||||
{
|
||||
VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT,
|
||||
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD,
|
||||
VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DECIMAL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ASCII translation tables
|
||||
*/
|
||||
|
||||
static const BYTE asciiTable1[10]=
|
||||
{
|
||||
')','!','@','#','$','%','^','&','*','('
|
||||
};
|
||||
static const BYTE asciiTable2[16]=
|
||||
{
|
||||
'0','1','2','3','4','5','6','7','8','9','*','+',0,'-','.','/'
|
||||
};
|
||||
static const BYTE asciiTable3[37]=
|
||||
{
|
||||
';','=',',','-','.','/','`', 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'[', '\\', ']', '\''
|
||||
};
|
||||
static const BYTE asciiTable4[37]=
|
||||
{
|
||||
':','+','<','_','>','?','~', 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'{', '|', '}', '"'
|
||||
};
|
||||
|
||||
VOID STDCALL
|
||||
KdpServiceDispatcher(ULONG Code, PVOID Context1, PVOID Context2);
|
||||
|
||||
static LONG DoSystemDebug = -1;
|
||||
static BOOLEAN InSysRq = FALSE;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static void KbdWrite(int addr,BYTE data)
|
||||
/*
|
||||
* FUNCTION: Write data to keyboard
|
||||
*/
|
||||
{
|
||||
BYTE status;
|
||||
|
||||
do
|
||||
{
|
||||
status=READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT); // Wait until input buffer empty
|
||||
} while(status & KBD_IBF);
|
||||
WRITE_PORT_UCHAR((PUCHAR)addr,data);
|
||||
}
|
||||
|
||||
static int KbdReadData(void)
|
||||
/*
|
||||
* FUNCTION: Read data from port 0x60
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
BYTE status,data;
|
||||
|
||||
i=500000;
|
||||
do
|
||||
{
|
||||
status=READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT);
|
||||
if (!(status & KBD_OBF)) // Check if data available
|
||||
continue;
|
||||
data=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
|
||||
if (status & (KBD_GTO | KBD_PERR)) // Check for timeout error
|
||||
continue;
|
||||
return data;
|
||||
} while(--i);
|
||||
return -1; // Timed out
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set keyboard LED's
|
||||
*/
|
||||
|
||||
static void SetKeyboardLEDs(BYTE status)
|
||||
{
|
||||
KbdWrite(KBD_DATA_PORT,0xED);
|
||||
if (KbdReadData()!=KBD_ACK) // Error
|
||||
return;
|
||||
KbdWrite(KBD_DATA_PORT,status);
|
||||
KbdReadData();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process scan code
|
||||
*/
|
||||
|
||||
static void ProcessScanCode(BYTE scanCode,BOOL isDown)
|
||||
{
|
||||
switch(scanCode)
|
||||
{
|
||||
case 0x1D: // Ctrl
|
||||
if (extKey)
|
||||
{
|
||||
if (isDown)
|
||||
ctrlKeyState|=RIGHT_CTRL_PRESSED;
|
||||
else
|
||||
ctrlKeyState&=~RIGHT_CTRL_PRESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDown)
|
||||
ctrlKeyState|=LEFT_CTRL_PRESSED;
|
||||
else
|
||||
ctrlKeyState&=~LEFT_CTRL_PRESSED;
|
||||
}
|
||||
break;
|
||||
case 0x2A: // Left shift
|
||||
case 0x36: // Right shift
|
||||
if (isDown)
|
||||
ctrlKeyState|=SHIFT_PRESSED;
|
||||
else
|
||||
ctrlKeyState&=~SHIFT_PRESSED;
|
||||
break;
|
||||
case 0x38: // Alt
|
||||
if (extKey)
|
||||
{
|
||||
if (isDown)
|
||||
ctrlKeyState|=RIGHT_ALT_PRESSED;
|
||||
else
|
||||
ctrlKeyState&=~RIGHT_ALT_PRESSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDown)
|
||||
ctrlKeyState|=LEFT_ALT_PRESSED;
|
||||
else
|
||||
ctrlKeyState&=~LEFT_ALT_PRESSED;
|
||||
}
|
||||
break;
|
||||
case 0x3A: // CapsLock
|
||||
if (ctrlKeyState & CTRL_PRESSED)
|
||||
break;
|
||||
if (isDown)
|
||||
{
|
||||
if (!capsDown)
|
||||
{
|
||||
capsDown=1;
|
||||
if (ctrlKeyState & CAPSLOCK_ON)
|
||||
{
|
||||
ledStatus&=~KBD_LED_CAPS;
|
||||
ctrlKeyState&=~CAPSLOCK_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
ledStatus|=KBD_LED_CAPS;
|
||||
ctrlKeyState|=CAPSLOCK_ON;
|
||||
}
|
||||
SetKeyboardLEDs(ledStatus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
capsDown=0;
|
||||
}
|
||||
break;
|
||||
case 0x45: // NumLock
|
||||
if (ctrlKeyState & CTRL_PRESSED)
|
||||
break;
|
||||
if (isDown)
|
||||
{
|
||||
if (!numDown)
|
||||
{
|
||||
numDown=1;
|
||||
if (ctrlKeyState & NUMLOCK_ON)
|
||||
{
|
||||
ledStatus&=~KBD_LED_NUM;
|
||||
ctrlKeyState&=~NUMLOCK_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
ledStatus|=KBD_LED_NUM;
|
||||
ctrlKeyState|=NUMLOCK_ON;
|
||||
}
|
||||
SetKeyboardLEDs(ledStatus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numDown=0;
|
||||
}
|
||||
break;
|
||||
case 0x46: // ScrollLock
|
||||
if (ctrlKeyState & CTRL_PRESSED)
|
||||
break;
|
||||
if (isDown)
|
||||
{
|
||||
if (!scrollDown)
|
||||
{
|
||||
scrollDown=1;
|
||||
if (ctrlKeyState & SCROLLLOCK_ON)
|
||||
{
|
||||
ledStatus&=~KBD_LED_SCROLL;
|
||||
ctrlKeyState&=~SCROLLLOCK_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
ledStatus|=KBD_LED_SCROLL;
|
||||
ctrlKeyState|=SCROLLLOCK_ON;
|
||||
}
|
||||
SetKeyboardLEDs(ledStatus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollDown=0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate virtual key code to ASCII
|
||||
*/
|
||||
|
||||
static BYTE VirtualToAscii(WORD keyCode,BOOL isDown)
|
||||
{
|
||||
if ((ctrlKeyState & ALT_PRESSED)&&(ctrlKeyState & CTRL_PRESSED))
|
||||
return 0; // Ctrl+Alt+char always 0
|
||||
if ((!isDown)&&(ctrlKeyState & ALT_PRESSED))
|
||||
return 0; // Alt+char is 0 when key is released
|
||||
|
||||
if (ctrlKeyState & CTRL_PRESSED)
|
||||
{
|
||||
if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
|
||||
return keyCode-VK_A+1;
|
||||
switch(keyCode)
|
||||
{
|
||||
case VK_SPACE:
|
||||
return ' ';
|
||||
case VK_BACK:
|
||||
return 127;
|
||||
case VK_RETURN:
|
||||
return '\r';
|
||||
case 219: /* [ */
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return 0;
|
||||
return 27;
|
||||
case 220: /* \ */
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return 0;
|
||||
return 28;
|
||||
case 221: /* ] */
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return 0;
|
||||
return 29;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
|
||||
{
|
||||
if (ctrlKeyState & CAPSLOCK_ON)
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return keyCode-VK_A+'a';
|
||||
else
|
||||
return keyCode-VK_A+'A';
|
||||
else
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return keyCode-VK_A+'A';
|
||||
else
|
||||
return keyCode-VK_A+'a';
|
||||
}
|
||||
|
||||
if ((keyCode>=VK_0)&&(keyCode<=VK_9))
|
||||
{
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return asciiTable1[keyCode-VK_0];
|
||||
else
|
||||
return keyCode-VK_0+'0';
|
||||
}
|
||||
|
||||
if ((keyCode>=VK_NUMPAD0)&&(keyCode<=VK_DIVIDE))
|
||||
return asciiTable2[keyCode-VK_NUMPAD0];
|
||||
|
||||
if ((keyCode>=186)&&(keyCode<=222))
|
||||
{
|
||||
if (ctrlKeyState & SHIFT_PRESSED)
|
||||
return asciiTable4[keyCode-186];
|
||||
else
|
||||
return asciiTable3[keyCode-186];
|
||||
}
|
||||
|
||||
switch(keyCode)
|
||||
{
|
||||
case VK_SPACE:
|
||||
return ' ';
|
||||
case VK_RETURN:
|
||||
return '\r';
|
||||
case VK_BACK:
|
||||
return 8;
|
||||
case VK_TAB:
|
||||
return 9;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate scan code to virtual key code
|
||||
*/
|
||||
|
||||
static WORD ScanToVirtual(BYTE scanCode)
|
||||
{
|
||||
if ((scanCode>=0x47)&&(scanCode<=0x53)&&(ctrlKeyState & NUMLOCK_ON)&&
|
||||
(!extKey)&&(!(ctrlKeyState & SHIFT_PRESSED)))
|
||||
return vkKeypadTable[scanCode-0x47];
|
||||
if ((scanCode==0x35)&&(extKey)) // Gray divide
|
||||
return VK_DIVIDE;
|
||||
if ((scanCode==0x37)&&(extKey)) // Print screen
|
||||
return VK_PRINT;
|
||||
return vkTable[scanCode];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Debug request handler
|
||||
*/
|
||||
|
||||
static VOID STDCALL
|
||||
KbdWorkItemRoutine(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PVOID Context)
|
||||
{
|
||||
LONG Debug;
|
||||
|
||||
Debug = InterlockedExchange(&DoSystemDebug, -1);
|
||||
if (Debug != -1)
|
||||
{
|
||||
KdpServiceDispatcher(TAG('R', 'o', 's', ' '), (PVOID)Debug, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard IRQ handler
|
||||
*/
|
||||
|
||||
static VOID STDCALL
|
||||
KbdDpcRoutine(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
{
|
||||
PIRP Irp = (PIRP)SystemArgument2;
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
|
||||
|
||||
if (SystemArgument1 == NULL && DoSystemDebug != -1)
|
||||
{
|
||||
if (KbdWorkItem != NULL && DoSystemDebug == 10) /* 10 is Tab + K (enter kernel debugger) */
|
||||
{
|
||||
IoQueueWorkItem(KbdWorkItem, (PIO_WORKITEM_ROUTINE)KbdWorkItemRoutine, DelayedWorkQueue, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
KdpServiceDispatcher(TAG('R', 'o', 's', ' '), (PVOID)DoSystemDebug, NULL);
|
||||
DoSystemDebug = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
|
||||
DeviceObject,Irp);
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
IoStartNextPacket(DeviceObject,FALSE);
|
||||
}
|
||||
|
||||
|
||||
static BOOLEAN STDCALL
|
||||
KeyboardHandler(PKINTERRUPT Interrupt,
|
||||
PVOID Context)
|
||||
{
|
||||
BYTE thisKey;
|
||||
BOOL isDown;
|
||||
static BYTE lastKey;
|
||||
CHAR Status;
|
||||
PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
|
||||
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
/*
|
||||
* Check status
|
||||
*/
|
||||
Status = READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT);
|
||||
if (!(Status & KBD_OBF))
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
// Read scan code
|
||||
thisKey=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
|
||||
|
||||
// Call hook routine. May change scancode value.
|
||||
if (deviceExtension->IsrHookCallback) {
|
||||
BOOLEAN cont = FALSE, ret;
|
||||
//BUG BUG: rewrite to have valid CurrentScanState!!!
|
||||
ret = (*deviceExtension->IsrHookCallback)(
|
||||
deviceObject,
|
||||
NULL,//&deviceExtension->CurrentInput,
|
||||
NULL,//&deviceExtension->CurrentOutput,
|
||||
Status,
|
||||
&thisKey, //&scanCode,
|
||||
&cont,
|
||||
NULL //&deviceExtension->CurrentScanState
|
||||
);
|
||||
|
||||
if (!cont) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((thisKey==0xE0)||(thisKey==0xE1)) // Extended key
|
||||
{
|
||||
extKey=1; // Wait for next byte
|
||||
lastKey=thisKey;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
isDown=!(thisKey & 0x80);
|
||||
thisKey&=0x7F;
|
||||
|
||||
// The keyboard maintains its own internal caps lock and num lock
|
||||
// statuses. In caps lock mode E0 AA precedes make code and
|
||||
// E0 2A follow break code. In num lock mode, E0 2A precedes
|
||||
// make code and E0 AA follow break code. We maintain our own caps lock
|
||||
// and num lock statuses, so we will just ignore these.
|
||||
// Some keyboards have L-Shift/R-Shift modes instead of caps lock
|
||||
// mode. If right shift pressed, E0 B6 / E0 36 pairs generated.
|
||||
if (extKey & ((thisKey==0x2A)||(thisKey==0x36)))
|
||||
{
|
||||
extKey=0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check for PAUSE sequence
|
||||
if (extKey && (lastKey==0xE1))
|
||||
{
|
||||
if (thisKey==0x1D)
|
||||
lastKey=0xFF; // Sequence is OK
|
||||
else
|
||||
extKey=0;
|
||||
return FALSE;
|
||||
}
|
||||
if (extKey && (lastKey==0xFF))
|
||||
{
|
||||
if (thisKey!=0x45)
|
||||
{
|
||||
extKey=0; // Bad sequence
|
||||
return FALSE;
|
||||
}
|
||||
thisKey=0x7F; // Pseudo-code for PAUSE
|
||||
}
|
||||
|
||||
ProcessScanCode(thisKey,isDown);
|
||||
|
||||
// DbgPrint("Key: %c\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
|
||||
// DbgPrint("Key: %x\n",ScanToVirtual(thisKey));
|
||||
if (ScanToVirtual(thisKey) == VK_TAB && isDown)
|
||||
{
|
||||
InSysRq = TRUE;
|
||||
}
|
||||
else if (ScanToVirtual(thisKey) == VK_TAB && !isDown)
|
||||
{
|
||||
InSysRq = FALSE;
|
||||
}
|
||||
else if (InSysRq == TRUE && ScanToVirtual(thisKey) >= VK_A &&
|
||||
ScanToVirtual(thisKey) <= VK_Z && isDown)
|
||||
{
|
||||
InterlockedExchange(&DoSystemDebug, ScanToVirtual(thisKey) - VK_A);
|
||||
KeInsertQueueDpc(&KbdDpc, NULL, NULL);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (CurrentIrp!=NULL)
|
||||
{
|
||||
KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
|
||||
CurrentIrp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
rec[KeysRead].bKeyDown=isDown;
|
||||
rec[KeysRead].wRepeatCount=1;
|
||||
rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey);
|
||||
rec[KeysRead].wVirtualScanCode=thisKey;
|
||||
rec[KeysRead].uChar.AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown);
|
||||
rec[KeysRead].dwControlKeyState=ctrlKeyState;
|
||||
if (extKey)
|
||||
{
|
||||
rec[KeysRead].dwControlKeyState|=ENHANCED_KEY;
|
||||
extKey = 0;
|
||||
}
|
||||
KeysRead++;
|
||||
DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead);
|
||||
if (KeysRead==KeysRequired)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Context;
|
||||
KeInsertQueueDpc(&KbdDpc,DeviceObject,CurrentIrp);
|
||||
CurrentIrp->IoStatus.Information = KeysRead * sizeof(KEY_EVENT_RECORD);
|
||||
CurrentIrp=NULL;
|
||||
}
|
||||
CHECKPOINT;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Buffer is full ?
|
||||
if (keysInBuffer==KBD_BUFFER_SIZE) // Buffer is full
|
||||
{
|
||||
extKey=0;
|
||||
return(TRUE);
|
||||
}
|
||||
kbdBuffer[bufHead].bKeyDown=isDown;
|
||||
kbdBuffer[bufHead].wRepeatCount=1;
|
||||
kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey);
|
||||
kbdBuffer[bufHead].wVirtualScanCode=thisKey;
|
||||
kbdBuffer[bufHead].uChar.UnicodeChar=0;
|
||||
// kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey);
|
||||
kbdBuffer[bufHead].uChar.AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown);
|
||||
kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState;
|
||||
if (extKey)
|
||||
kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY;
|
||||
bufHead++;
|
||||
bufHead&=KBD_WRAP_MASK; // Modulo KBD_BUFFER_SIZE
|
||||
keysInBuffer++;
|
||||
extKey=0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Initialize keyboard
|
||||
//
|
||||
static void KeyboardConnectInterrupt(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
NTSTATUS Status;
|
||||
|
||||
MappedIrq = HalGetInterruptVector(Internal,
|
||||
0,
|
||||
0,
|
||||
KEYBOARD_IRQ,
|
||||
&Dirql,
|
||||
&Affinity);
|
||||
Status = IoConnectInterrupt(&KbdInterrupt,
|
||||
KeyboardHandler,
|
||||
(PVOID)DeviceObject,
|
||||
NULL,
|
||||
MappedIrq,
|
||||
Dirql,
|
||||
Dirql,
|
||||
0,
|
||||
FALSE,
|
||||
Affinity,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
KbdClearInput(VOID)
|
||||
{
|
||||
ULONG i;
|
||||
CHAR Status;
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
Status = READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT);
|
||||
if (!(Status & KBD_OBF))
|
||||
{
|
||||
return;
|
||||
}
|
||||
(VOID)READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
|
||||
}
|
||||
}
|
||||
|
||||
static int InitializeKeyboard(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
// Initialize variables
|
||||
bufHead=0;
|
||||
bufTail=0;
|
||||
keysInBuffer=0;
|
||||
ledStatus=0;
|
||||
capsDown=0;
|
||||
numDown=0;
|
||||
scrollDown=0;
|
||||
ctrlKeyState=0;
|
||||
extKey=0;
|
||||
|
||||
KbdClearInput();
|
||||
KeyboardConnectInterrupt(DeviceObject);
|
||||
KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
|
||||
KbdWorkItem = IoAllocateWorkItem(DeviceObject);
|
||||
if (KbdWorkItem == NULL)
|
||||
{
|
||||
DPRINT("Warning: Couldn't allocate work item!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from keyboard buffer
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
KbdSynchronizeRoutine(PVOID Context)
|
||||
{
|
||||
PIRP Irp = (PIRP)Context;
|
||||
KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)Irp->AssociatedIrp.SystemBuffer;
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
|
||||
int i;
|
||||
|
||||
DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer);
|
||||
NrToRead = min(NrToRead,keysInBuffer);
|
||||
|
||||
DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n",
|
||||
NrToRead,stk->Parameters.Read.Length);
|
||||
DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD));
|
||||
for (i=0;i<NrToRead;i++)
|
||||
{
|
||||
memcpy(&rec[i],&kbdBuffer[bufTail],sizeof(KEY_EVENT_RECORD));
|
||||
bufTail++;
|
||||
bufTail&=KBD_WRAP_MASK;
|
||||
keysInBuffer--;
|
||||
}
|
||||
if ((stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead)
|
||||
{
|
||||
Irp->IoStatus.Information = stk->Parameters.Read.Length;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
|
||||
KeysRead=NrToRead;
|
||||
CurrentIrp=Irp;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
VOID STDCALL KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
#endif
|
||||
|
||||
DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
if (KeSynchronizeExecution(KbdInterrupt, KbdSynchronizeRoutine, Irp))
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
oldIrql = KeGetCurrentIrql();
|
||||
if (oldIrql < DISPATCH_LEVEL)
|
||||
{
|
||||
KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
|
||||
IoStartNextPacket (DeviceObject, FALSE);
|
||||
KeLowerIrql(oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoStartNextPacket (DeviceObject, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length);
|
||||
DPRINT("KeysRequired %d\n",KeysRequired);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL KbdInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk;
|
||||
PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard;
|
||||
PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||||
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (stk->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
/*-----------------11/29/2001 4:12PM----------------
|
||||
* This internal ioctrl belongs in i8042 driver. Should be
|
||||
* moved to the appropriate driver later.
|
||||
* --------------------------------------------------*/
|
||||
case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
|
||||
|
||||
if (stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(INTERNAL_I8042_HOOK_KEYBOARD))
|
||||
{
|
||||
DPRINT(("Keyboard IOCTL_INTERNAL_I8042_HOOK_KEYBOARD invalid buffer size\n"));
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Copy the values if they are filled in
|
||||
//
|
||||
hookKeyboard = (PINTERNAL_I8042_HOOK_KEYBOARD)
|
||||
stk->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
|
||||
DevExt->HookContext = hookKeyboard->Context;
|
||||
if (hookKeyboard->InitializationRoutine) {
|
||||
DbgPrint("Keyboard: InitializationHookCallback NOT IMPLEMENTED\n");
|
||||
DevExt->InitializationHookCallback =
|
||||
hookKeyboard->InitializationRoutine;
|
||||
}
|
||||
|
||||
if (hookKeyboard->IsrRoutine) {
|
||||
DevExt->IsrHookCallback = hookKeyboard->IsrRoutine;
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("DeviceObject %x\n",DeviceObject);
|
||||
DPRINT("Irp %x\n",Irp);
|
||||
|
||||
DPRINT("IRP_MJ_CREATE %d stk->MajorFunction %d\n",
|
||||
IRP_MJ_CREATE, stk->MajorFunction);
|
||||
DPRINT("AlreadyOpened %d\n",AlreadyOpened);
|
||||
|
||||
switch (stk->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
if (AlreadyOpened == TRUE)
|
||||
{
|
||||
CHECKPOINT;
|
||||
// Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECKPOINT;
|
||||
Status = STATUS_SUCCESS;
|
||||
AlreadyOpened = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IRP_MJ_READ:
|
||||
DPRINT("Handling Read request\n");
|
||||
DPRINT("Queueing packet\n");
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject,Irp,NULL,NULL);
|
||||
return(STATUS_PENDING);
|
||||
|
||||
default:
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
DPRINT("Status %d\n",Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||
PUNICODE_STRING RegistryPath)
|
||||
/*
|
||||
* FUNCTION: Module entry point
|
||||
*/
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
UNICODE_STRING DeviceName = ROS_STRING_INITIALIZER(L"\\Device\\Keyboard");
|
||||
UNICODE_STRING SymlinkName = ROS_STRING_INITIALIZER(L"\\??\\Keyboard");
|
||||
|
||||
DPRINT("Keyboard Driver 0.0.4\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
|
||||
KbdInternalDeviceControl;
|
||||
|
||||
DriverObject->DriverStartIo = KbdStartIo;
|
||||
|
||||
IoCreateDevice(DriverObject,
|
||||
sizeof(DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_KEYBOARD,
|
||||
0,
|
||||
TRUE,
|
||||
&DeviceObject);
|
||||
|
||||
RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
|
||||
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
|
||||
InitializeKeyboard( DeviceObject );
|
||||
|
||||
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
#ifndef _KEYBOARD_H_
|
||||
#define _KEYBOARD_H_
|
||||
#include <ddk/ntddkbd.h>
|
||||
#include <ddk/ntdd8042.h>
|
||||
|
||||
|
||||
/*-----------------------------------------------------
|
||||
* DeviceExtension
|
||||
* --------------------------------------------------*/
|
||||
typedef struct _DEVICE_EXTENSION
|
||||
{
|
||||
|
||||
PI8042_KEYBOARD_INITIALIZATION_ROUTINE InitializationHookCallback;
|
||||
PI8042_KEYBOARD_ISR IsrHookCallback;
|
||||
PVOID HookContext;
|
||||
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
/*
|
||||
* Some defines
|
||||
*/
|
||||
|
||||
#define KEYBOARD_IRQ 1
|
||||
#define KBD_BUFFER_SIZE 32
|
||||
#define KBD_WRAP_MASK 0x1F
|
||||
|
||||
#define disable() __asm__("cli\n\t")
|
||||
#define enable() __asm__("sti\n\t")
|
||||
|
||||
#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
|
||||
#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard controller ports
|
||||
*/
|
||||
|
||||
#define KBD_DATA_PORT 0x60
|
||||
#define KBD_CTRL_PORT 0x64
|
||||
|
||||
|
||||
/*
|
||||
* Controller commands
|
||||
*/
|
||||
|
||||
#define KBD_READ_MODE 0x20
|
||||
#define KBD_WRITE_MODE 0x60
|
||||
#define KBD_SELF_TEST 0xAA
|
||||
#define KBD_LINE_TEST 0xAB
|
||||
#define KBD_CTRL_ENABLE 0xAE
|
||||
|
||||
/*
|
||||
* Keyboard commands
|
||||
*/
|
||||
|
||||
#define KBD_ENABLE 0xF4
|
||||
#define KBD_DISABLE 0xF5
|
||||
#define KBD_RESET 0xFF
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard responces
|
||||
*/
|
||||
|
||||
#define KBD_ACK 0xFA
|
||||
#define KBD_BATCC 0xAA
|
||||
|
||||
|
||||
/*
|
||||
* Controller status register bits
|
||||
*/
|
||||
|
||||
#define KBD_OBF 0x01
|
||||
#define KBD_IBF 0x02
|
||||
#define KBD_GTO 0x40
|
||||
#define KBD_PERR 0x80
|
||||
|
||||
|
||||
/*
|
||||
* LED bits
|
||||
*/
|
||||
|
||||
#define KBD_LED_SCROLL 0x01
|
||||
#define KBD_LED_NUM 0x02
|
||||
#define KBD_LED_CAPS 0x04
|
||||
|
||||
#endif // _KEYBOARD_H_
|
|
@ -1,7 +0,0 @@
|
|||
/* $Id$ */
|
||||
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Keyboard Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "keyboard\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "keyboard.sys\0"
|
||||
#include <reactos/version.rc>
|
|
@ -1,17 +0,0 @@
|
|||
# $Id$
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET_BOOTSTRAP = yes
|
||||
|
||||
TARGET_TYPE = driver
|
||||
|
||||
TARGET_NAME = keyboard
|
||||
|
||||
TARGET_CFLAGS = -Wall -Werror
|
||||
|
||||
TARGET_OBJECTS = $(TARGET_NAME).o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
|
@ -1,157 +0,0 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "keyboard.h"
|
||||
#include "mouse.h"
|
||||
|
||||
/* This reads the controller status port, and does the appropriate
|
||||
action. It requires that we hold the keyboard controller spinlock. */
|
||||
|
||||
int controller_read_data(void);
|
||||
unsigned handle_event(void)
|
||||
{
|
||||
unsigned status = controller_read_status();
|
||||
unsigned int work;
|
||||
|
||||
for(work = 0; (work < 10000) && ((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0); work++)
|
||||
{
|
||||
unsigned scancode;
|
||||
|
||||
scancode = controller_read_input();
|
||||
|
||||
#if 0
|
||||
/* Ignore error bytes. */
|
||||
|
||||
if((status &(CONTROLLER_STATUS_GENERAL_TIMEOUT |
|
||||
CONTROLLER_STATUS_PARITY_ERROR)) == 0)
|
||||
#endif
|
||||
{
|
||||
if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
// mouse_handle_event(scancode); we just use the mouse handler directly..
|
||||
}
|
||||
else
|
||||
{
|
||||
// keyboard_handle_event(scancode);
|
||||
}
|
||||
}
|
||||
|
||||
status = controller_read_status();
|
||||
|
||||
}
|
||||
|
||||
if(work == 10000)
|
||||
{
|
||||
DbgPrint("PSAUX: Keyboard controller jammed\n");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for keyboard controller input buffer to drain.
|
||||
Quote from PS/2 System Reference Manual:
|
||||
"Address hex 0060 and address hex 0064 should be written only
|
||||
when the input-buffer-full bit and output-buffer-full bit in the
|
||||
Controller Status register are set 0." */
|
||||
|
||||
void controller_wait(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
Millisecond_Timeout.QuadPart = -10000L;
|
||||
|
||||
for(timeout = 0; timeout < CONTROLLER_TIMEOUT; timeout++)
|
||||
{
|
||||
// "handle_keyboard_event()" will handle any incoming events
|
||||
// while we wait -- keypresses or mouse movement
|
||||
|
||||
unsigned char status = handle_event();
|
||||
|
||||
if((status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0) return;
|
||||
|
||||
// Sleep for one millisecond
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
|
||||
DbgPrint("PSAUX: Keyboard timed out\n");
|
||||
}
|
||||
|
||||
/* Wait for input from the keyboard controller. */
|
||||
|
||||
int controller_wait_for_input(void)
|
||||
{
|
||||
int timeout;
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
Millisecond_Timeout.QuadPart = -10000L;
|
||||
|
||||
for(timeout = KEYBOARD_INIT_TIMEOUT; timeout > 0; timeout--)
|
||||
{
|
||||
int return_value = controller_read_data();
|
||||
|
||||
if(return_value >= 0) return return_value;
|
||||
|
||||
// Sleep for one millisecond
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
|
||||
DbgPrint("PSAUX: Timed out on waiting for input from controller\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write a command word to the keyboard controller. */
|
||||
|
||||
void controller_write_command_word(unsigned data)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_command(data);
|
||||
}
|
||||
|
||||
/* Write an output word to the keyboard controller. */
|
||||
|
||||
void controller_write_output_word(unsigned data)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_output(data);
|
||||
}
|
||||
|
||||
/* Empty the keyboard input buffer. */
|
||||
|
||||
void keyboard_clear_input(void)
|
||||
{
|
||||
int max_read;
|
||||
|
||||
for(max_read = 0; max_read < 100; max_read++)
|
||||
{
|
||||
if(controller_read_data() == KEYBOARD_NO_DATA)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read data from the keyboard controller. */
|
||||
|
||||
int controller_read_data(void)
|
||||
{
|
||||
int return_value = KEYBOARD_NO_DATA;
|
||||
unsigned status;
|
||||
|
||||
status = controller_read_status();
|
||||
if(status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL)
|
||||
{
|
||||
unsigned data = controller_read_input();
|
||||
|
||||
return_value = data;
|
||||
if(status &(CONTROLLER_STATUS_GENERAL_TIMEOUT |
|
||||
CONTROLLER_STATUS_PARITY_ERROR))
|
||||
{
|
||||
return_value = KEYBOARD_BAD_DATA;
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
/* Keyboard controller registers. */
|
||||
|
||||
#define CONTROLLER_REGISTER_STATUS 0x64
|
||||
#define CONTROLLER_REGISTER_CONTROL 0x64
|
||||
#define CONTROLLER_REGISTER_DATA 0x60
|
||||
|
||||
/* Keyboard controller commands. */
|
||||
/* Read mode bits. */
|
||||
|
||||
#define CONTROLLER_COMMAND_READ_MODE 0x20
|
||||
|
||||
/* Write mode bits. */
|
||||
|
||||
#define CONTROLLER_COMMAND_WRITE_MODE 0x60
|
||||
|
||||
/* Get controller version. */
|
||||
|
||||
#define CONTROLLER_COMMAND_GET_VERSION 0xA1
|
||||
|
||||
/* Disable mouse interface. */
|
||||
|
||||
#define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7
|
||||
|
||||
/* Enable mouse interface. */
|
||||
|
||||
#define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8
|
||||
|
||||
/* Mouse interface test. */
|
||||
|
||||
#define CONTROLLER_COMMAND_TEST_MOUSE 0xA9
|
||||
|
||||
/* Controller self test. */
|
||||
|
||||
#define CONTROLLER_COMMAND_SELF_TEST 0xAA
|
||||
|
||||
/* Keyboard interface test. */
|
||||
|
||||
#define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB
|
||||
|
||||
/* Keyboard interface disable. */
|
||||
|
||||
#define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD
|
||||
|
||||
/* Keyboard interface enable. */
|
||||
|
||||
#define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE
|
||||
|
||||
/* Write to output buffer as if initiated by the auxiliary device. */
|
||||
|
||||
#define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3
|
||||
|
||||
/* Write the following byte to the mouse. */
|
||||
|
||||
#define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4
|
||||
|
||||
/* Status Register Bits. */
|
||||
/* Keyboard output buffer full. */
|
||||
|
||||
#define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01
|
||||
|
||||
/* Keyboard input buffer full. */
|
||||
|
||||
#define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02
|
||||
|
||||
/* Self test successful. */
|
||||
|
||||
#define CONTROLLER_STATUS_SELF_TEST 0x04
|
||||
|
||||
/* Last write was a command write. (0 = data) */
|
||||
|
||||
#define CONTROLLER_STATUS_COMMAND 0x08
|
||||
|
||||
/* Zero if keyboard locked. */
|
||||
|
||||
#define CONTROLLER_STATUS_UNLOCKED 0x10
|
||||
|
||||
/* Mouse output buffer full. */
|
||||
|
||||
#define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20
|
||||
|
||||
/* General receive/xmit timeout. */
|
||||
|
||||
#define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40
|
||||
|
||||
/* Parity error. */
|
||||
|
||||
#define CONTROLLER_STATUS_PARITY_ERROR 0x80
|
||||
|
||||
#define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \
|
||||
CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL)
|
||||
|
||||
/* Controller mode register bits. */
|
||||
/* Keyboard data generate IRQ1. */
|
||||
|
||||
#define CONTROLLER_MODE_KEYBOARD_INTERRUPT 0x01
|
||||
|
||||
/* Mouse data generate IRQ12. */
|
||||
|
||||
#define CONTROLLER_MODE_MOUSE_INTERRUPT 0x02
|
||||
|
||||
/* The system flag. (?) */
|
||||
|
||||
#define CONTROLLER_MODE_SYS 0x04
|
||||
|
||||
/* The keylock doesn't affect the keyboard if set. */
|
||||
|
||||
#define CONTROLLER_MODE_NO_KEYLOCK 0x08
|
||||
|
||||
/* Disable keyboard interface. */
|
||||
|
||||
#define CONTROLLER_MODE_DISABLE_KEYBOARD 0x10
|
||||
|
||||
/* Disable mouse interface. */
|
||||
|
||||
#define CONTROLLER_MODE_DISABLE_MOUSE 0x20
|
||||
|
||||
/* Scan code conversion to PC format. */
|
||||
|
||||
#define CONTROLLER_MODE_KCC 0x40
|
||||
#define CONTROLLER_MODE_RFU 0x80
|
||||
|
||||
/* Timeout in ms for sending to keyboard controller. */
|
||||
|
||||
#define CONTROLLER_TIMEOUT 250
|
||||
|
||||
/* Hardware defines. */
|
||||
|
||||
#define CONTROLLER_PORT_BASE 0x60
|
||||
#define CONTROLLER_PORTS 0x10
|
||||
|
||||
/* Macros for accessing the keyboard controller on this platform. */
|
||||
|
||||
#define controller_read_input() READ_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_DATA)
|
||||
#define controller_read_status() READ_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_STATUS)
|
||||
#define controller_write_output(value) WRITE_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_DATA, value)
|
||||
#define controller_write_command(value) WRITE_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_CONTROL, value)
|
||||
void controller_write_command_word(unsigned data);
|
|
@ -1,51 +0,0 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
/* Timeout in ms for keyboard command acknowledge. */
|
||||
|
||||
#define KEYBOARD_TIMEOUT 1000
|
||||
|
||||
/* Timeout in ms for initializing the keyboard. */
|
||||
|
||||
#define KEYBOARD_INIT_TIMEOUT 1000
|
||||
|
||||
/* Keyboard commands. */
|
||||
|
||||
#define KEYBOARD_COMMAND_SET_LEDS 0xED
|
||||
#define KEYBOARD_COMMAND_SET_RATE 0xF3
|
||||
#define KEYBOARD_COMMAND_ENABLE 0xF4
|
||||
#define KEYBOARD_COMMAND_DISABLE 0xF5
|
||||
#define KEYBOARD_COMMAND_RESET 0xFF
|
||||
|
||||
/* Keyboard replies. */
|
||||
/* Power on reset. */
|
||||
|
||||
#define KEYBOARD_REPLY_POWER_ON_RESET 0xAA
|
||||
|
||||
/* Acknowledgement of previous command. */
|
||||
|
||||
#define KEYBOARD_REPLY_ACK 0xFA
|
||||
|
||||
/* Command NACK, send the command again. */
|
||||
|
||||
#define KEYBOARD_REPLY_RESEND 0xFE
|
||||
|
||||
/* Hardware defines. */
|
||||
|
||||
#define KEYBOARD_IRQ 1
|
||||
|
||||
/* Return values from keyboard_read_data (). */
|
||||
/* No data. */
|
||||
|
||||
#define KEYBOARD_NO_DATA (-1)
|
||||
|
||||
/* Parity or other error. */
|
||||
|
||||
#define KEYBOARD_BAD_DATA (-2)
|
||||
|
||||
/* Common variables. */
|
||||
|
||||
int mouse_replies_expected;
|
||||
BOOLEAN has_mouse;
|
||||
// mailbox_id_type keyboard_target_mailbox_id;
|
||||
unsigned keyboard_pressed_keys[16];
|
|
@ -1,239 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
int SendCommand(PDEVICE_EXTENSION DeviceExtension, unsigned char *param, int command);
|
||||
void PS2PPProcessPacket(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input, int *wheel)
|
||||
{
|
||||
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)); */
|
||||
|
||||
*wheel = (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)); */
|
||||
|
||||
*wheel = (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 (SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11))
|
||||
return -1;
|
||||
|
||||
for (i = 6; i >= 0; i -= 2) {
|
||||
d = (command >> i) & 3;
|
||||
if(SendCommand(DeviceExtension, &d, PSMOUSE_CMD_SETRES))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SendCommand(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;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
|
||||
if (DeviceExtension->SmartScroll == 1)
|
||||
param[0] = 1;
|
||||
else
|
||||
if (DeviceExtension->SmartScroll > 2)
|
||||
return;
|
||||
|
||||
/* else leave param[0] == 0 to disable */
|
||||
SendCommand(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 PS2PPSet800dpi(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param = 3;
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, ¶m, PSMOUSE_CMD_SETRES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or
|
||||
* touchpad.
|
||||
*/
|
||||
|
||||
int PS2PPDetectModel(PDEVICE_EXTENSION DeviceExtension, unsigned char *param)
|
||||
{
|
||||
int i;
|
||||
//char *vendor, *name;
|
||||
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->MouseModel = ((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->MouseModel)
|
||||
DeviceExtension->MouseType = PSMOUSE_PS2PP;
|
||||
|
||||
if (DeviceExtension->MouseType == PSMOUSE_PS2PP) {
|
||||
|
||||
/* for (i = 0; logitech_4btn[i] != -1; i++)
|
||||
if (logitech_4btn[i] == DeviceExtension->MouseModel)
|
||||
set_bit(BTN_SIDE, psmouse->dev.keybit);
|
||||
*/
|
||||
for (i = 0; logitech_wheel[i] != -1; i++)
|
||||
if (logitech_wheel[i] == DeviceExtension->MouseModel) {
|
||||
// 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->MouseModel) {
|
||||
/* 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->MouseModel == 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 */
|
||||
SendCommand(DeviceExtension, param, 0x30d1);
|
||||
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */
|
||||
SendCommand(DeviceExtension, param, 0x30d1);
|
||||
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */
|
||||
SendCommand(DeviceExtension, param, 0x30d1);
|
||||
|
||||
param[0] = 0;
|
||||
if (!SendCommand(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;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* 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,15 +0,0 @@
|
|||
# $Id$
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET_TYPE = driver
|
||||
|
||||
TARGET_NAME = psaux
|
||||
|
||||
TARGET_CFLAGS = -Wall -Werror
|
||||
|
||||
TARGET_OBJECTS = $(TARGET_NAME).o controller.o mouse.o logips2pp.o synaptics.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
|
@ -1,679 +0,0 @@
|
|||
/*
|
||||
** PS/2 Mouse Driver
|
||||
** Written by Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
||||
** For ReactOS (www.reactos.com)
|
||||
** Adapted from the linux 2.6 mouse driver
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/ntddmou.h>
|
||||
#include "controller.h"
|
||||
#include "mouse.h"
|
||||
#include "psaux.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
int InitSynaptics(PDEVICE_EXTENSION DeviceExtension);
|
||||
void PS2PPProcessPacket(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input, int *wheel);
|
||||
void PS2PPSet800dpi(PDEVICE_EXTENSION DeviceExtension);
|
||||
int PS2PPDetectModel(PDEVICE_EXTENSION DeviceExtension, unsigned char *param);
|
||||
|
||||
// Parse incoming packets
|
||||
BOOLEAN FASTCALL
|
||||
ParsePackets(PDEVICE_EXTENSION DeviceExtension, PMOUSE_INPUT_DATA Input)
|
||||
{
|
||||
ULONG ButtonsDiff;
|
||||
int wheel = 0;
|
||||
unsigned char *packet = DeviceExtension->MouseBuffer;
|
||||
|
||||
/* Determine the current state of the buttons */
|
||||
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)
|
||||
PS2PPProcessPacket(DeviceExtension, Input, &wheel);
|
||||
|
||||
/*
|
||||
* Scroll wheel on IntelliMice, scroll buttons on NetMice
|
||||
*/
|
||||
|
||||
if(DeviceExtension->MouseType == PSMOUSE_IMPS || DeviceExtension->MouseType == PSMOUSE_GENPS)
|
||||
{
|
||||
wheel = (int)(-(signed char) packet[3]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scroll wheel and buttons on IntelliMouse Explorer
|
||||
*/
|
||||
|
||||
if(DeviceExtension->MouseType == PSMOUSE_IMEX)
|
||||
{
|
||||
wheel = (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
|
||||
*/
|
||||
|
||||
Input->ButtonFlags = 0;
|
||||
ButtonsDiff = DeviceExtension->PreviousButtons ^ Input->RawButtons;
|
||||
|
||||
/*
|
||||
* Generic PS/2 Mouse
|
||||
*/
|
||||
|
||||
if(ButtonsDiff & GPM_B_LEFT)
|
||||
Input->ButtonFlags |= ((Input->RawButtons & GPM_B_LEFT) ? MOUSE_BUTTON_1_DOWN : MOUSE_BUTTON_1_UP);
|
||||
|
||||
if(ButtonsDiff & GPM_B_RIGHT)
|
||||
Input->ButtonFlags |= ((Input->RawButtons & GPM_B_RIGHT) ? MOUSE_BUTTON_2_DOWN : MOUSE_BUTTON_2_UP);
|
||||
|
||||
if(ButtonsDiff & GPM_B_MIDDLE)
|
||||
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
|
||||
* 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(packet[1])
|
||||
Input->LastX = ((packet[0] & 0x10) ? (int)(packet[1] - 256) : (int) packet[1]);
|
||||
else
|
||||
Input->LastX = 0;
|
||||
|
||||
/* Determine LastY */
|
||||
if(packet[2])
|
||||
Input->LastY = -((packet[0] & 0x20) ? (int)(packet[2] - 256) : (int) packet[2]);
|
||||
else
|
||||
Input->LastY = 0;
|
||||
|
||||
/* Copy RawButtons to Previous Buttons for Input */
|
||||
DeviceExtension->PreviousButtons = Input->RawButtons;
|
||||
|
||||
if((wheel != 0) && (wheel >= -8) && (wheel <= 7))
|
||||
{
|
||||
Input->ButtonFlags |= MOUSE_WHEEL;
|
||||
Input->ButtonData = (UINT)(wheel * WHEEL_DELTA);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Handle a mouse event
|
||||
BOOLEAN STDCALL
|
||||
MouseHandler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PMOUSE_INPUT_DATA Input;
|
||||
ULONG Queue;
|
||||
BOOLEAN ret;
|
||||
unsigned scancode;
|
||||
unsigned status = controller_read_status();
|
||||
scancode = controller_read_input();
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Add this scancode to the mouse event queue. */
|
||||
DeviceExtension->MouseBuffer[DeviceExtension->MouseBufferPosition] = scancode;
|
||||
DeviceExtension->MouseBufferPosition++;
|
||||
|
||||
/* If the buffer is full, parse this event */
|
||||
if (DeviceExtension->MouseBufferPosition == DeviceExtension->MouseBufferSize)
|
||||
{
|
||||
Queue = DeviceExtension->ActiveQueue % 2;
|
||||
|
||||
/* Reset the buffer state. */
|
||||
DeviceExtension->MouseBufferPosition = 0;
|
||||
|
||||
/* Prevent buffer overflow */
|
||||
if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Input = &DeviceExtension->MouseInputData[Queue]
|
||||
[DeviceExtension->InputDataCount[Queue]];
|
||||
|
||||
ret = ParsePackets(DeviceExtension, Input);
|
||||
|
||||
/* Send the Input data to the Mouse Class driver */
|
||||
DeviceExtension->InputDataCount[Queue]++;
|
||||
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Write a PS/2 mouse command.
|
||||
static void mouse_write_command(int command)
|
||||
{
|
||||
controller_wait();
|
||||
controller_write_command(CONTROLLER_COMMAND_WRITE_MODE);
|
||||
controller_wait();
|
||||
controller_write_output(command);
|
||||
}
|
||||
|
||||
|
||||
// Sends a byte to the mouse
|
||||
static int SendByte(PDEVICE_EXTENSION DeviceExtension, unsigned char byte)
|
||||
{
|
||||
int timeout = 100; /* 100 msec */
|
||||
int scancode;
|
||||
unsigned char status;
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
Millisecond_Timeout.QuadPart = -10000L;
|
||||
|
||||
DeviceExtension->ack = 0;
|
||||
DeviceExtension->acking = 1;
|
||||
|
||||
controller_wait();
|
||||
controller_write_command(CONTROLLER_COMMAND_WRITE_MOUSE);
|
||||
controller_wait();
|
||||
controller_write_output(byte);
|
||||
while ((DeviceExtension->ack == 0) && timeout--)
|
||||
{
|
||||
status = controller_read_status();
|
||||
if((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
scancode = controller_read_input();
|
||||
if(scancode >= 0)
|
||||
{
|
||||
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->RepliesExpected)
|
||||
DeviceExtension->pkt[--DeviceExtension->RepliesExpected] = scancode;
|
||||
break;
|
||||
}
|
||||
return (int)(-(DeviceExtension->ack <= 0));
|
||||
}
|
||||
}
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
return (int)(-(DeviceExtension->ack <= 0));
|
||||
}
|
||||
|
||||
|
||||
// Send a PS/2 command to the mouse.
|
||||
int SendCommand(PDEVICE_EXTENSION DeviceExtension, unsigned char *param, int command)
|
||||
{
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
unsigned char status;
|
||||
int scancode;
|
||||
int timeout = 500; /* 500 msec */
|
||||
int send = (command >> 12) & 0xf;
|
||||
int receive = (command >> 8) & 0xf;
|
||||
int i;
|
||||
|
||||
Millisecond_Timeout.QuadPart = -10000L;
|
||||
|
||||
DeviceExtension->RepliesExpected = receive;
|
||||
if (command == PSMOUSE_CMD_RESET_BAT)
|
||||
timeout = 2000; /* 2 sec */
|
||||
|
||||
if (command & 0xff)
|
||||
if (SendByte(DeviceExtension, command & 0xff))
|
||||
return (int)(DeviceExtension->RepliesExpected = 0) - 1;
|
||||
|
||||
for (i = 0; i < send; i++)
|
||||
if (SendByte(DeviceExtension, param[i]))
|
||||
return (int)(DeviceExtension->RepliesExpected = 0) - 1;
|
||||
|
||||
while (DeviceExtension->RepliesExpected && timeout--)
|
||||
{
|
||||
if (DeviceExtension->RepliesExpected == 1 && command == PSMOUSE_CMD_RESET_BAT)
|
||||
timeout = 100;
|
||||
|
||||
if (DeviceExtension->RepliesExpected == 1 && command == PSMOUSE_CMD_GETID &&
|
||||
DeviceExtension->pkt[1] != 0xab && DeviceExtension->pkt[1] != 0xac)
|
||||
{
|
||||
DeviceExtension->RepliesExpected = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
status = controller_read_status();
|
||||
if((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
scancode = controller_read_input();
|
||||
if(scancode >= 0)
|
||||
{
|
||||
DeviceExtension->pkt[--DeviceExtension->RepliesExpected] = scancode;
|
||||
}
|
||||
}
|
||||
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
|
||||
for (i = 0; i < receive; i++)
|
||||
param[i] = DeviceExtension->pkt[(receive - 1) - i];
|
||||
|
||||
if (DeviceExtension->RepliesExpected)
|
||||
return (int)(DeviceExtension->RepliesExpected = 0) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// changes the resolution of the mouse
|
||||
void SetResolution(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[1];
|
||||
|
||||
if(DeviceExtension->MouseType == PSMOUSE_PS2PP && DeviceExtension->Resolution > 400)
|
||||
{
|
||||
PS2PPSet800dpi(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;
|
||||
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
}
|
||||
|
||||
|
||||
// Detect mouse models
|
||||
int TestMouseExtensions(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[4];
|
||||
int type = 0;
|
||||
|
||||
param[0] = 0;
|
||||
|
||||
// vendor = Generic
|
||||
// name = Mouse
|
||||
DeviceExtension->MouseModel = 0;
|
||||
|
||||
/*
|
||||
* Try Synaptics TouchPad magic ID
|
||||
*/
|
||||
param[0] = 0;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_GETINFO);
|
||||
if(param[1] == 0x47)
|
||||
{
|
||||
// vendor = Synaptics
|
||||
// name = TouchPad
|
||||
if(!InitSynaptics(DeviceExtension))
|
||||
return PSMOUSE_SYNAPTICS;
|
||||
else
|
||||
return PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Genius NetMouse magic init.
|
||||
*/
|
||||
param[0] = 3;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_GETINFO);
|
||||
if(param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55)
|
||||
{
|
||||
// vendor = Genius
|
||||
// name = Wheel Mouse
|
||||
// Features = 4th, 5th, Wheel
|
||||
return PSMOUSE_GENPS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Logitech magic ID.
|
||||
*/
|
||||
param[0] = 0;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRES);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
param[1] = 0;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_GETINFO);
|
||||
if(param[1])
|
||||
{
|
||||
type = PS2PPDetectModel(DeviceExtension, param);
|
||||
if(type)
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try IntelliMouse magic init.
|
||||
*/
|
||||
param[0] = 200;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 100;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 80;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_GETID);
|
||||
if(param[0] == 3)
|
||||
{
|
||||
// Features = Wheel
|
||||
|
||||
/*
|
||||
* Try IntelliMouse/Explorer magic init.
|
||||
*/
|
||||
param[0] = 200;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 200;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
param[0] = 80;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_GETID);
|
||||
if(param[0] == 4)
|
||||
{
|
||||
// name = Explorer Mouse
|
||||
// Features = 4th, 5th, Wheel
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// Detect if mouse is just a standard ps/2 mouse
|
||||
int TestMouse(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[4];
|
||||
|
||||
param[0] = param[1] = 0xa5;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if(SendCommand(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(DeviceExtension->NoExtensions)
|
||||
{
|
||||
return DeviceExtension->MouseType = PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
if(SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_RESET_DIS))
|
||||
return -1;
|
||||
|
||||
return DeviceExtension->MouseType = TestMouseExtensions(DeviceExtension);
|
||||
}
|
||||
|
||||
|
||||
// Initialize and enable the mouse
|
||||
void InitializeMouse(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
unsigned char param[4];
|
||||
|
||||
/*
|
||||
* We set the mouse report rate to a highest possible value.
|
||||
* We try 100 first in case mouse fails to set 200.
|
||||
*/
|
||||
|
||||
param[0] = 200;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
|
||||
param[0] = 100;
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETRATE);
|
||||
|
||||
SetResolution(DeviceExtension);
|
||||
SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_SETSCALE11);
|
||||
|
||||
/*
|
||||
* We set the mouse into streaming mode.
|
||||
*/
|
||||
|
||||
SendCommand(DeviceExtension, param, PSMOUSE_CMD_SETSTREAM);
|
||||
|
||||
/*
|
||||
* Last, we enable the mouse so that we get reports from it.
|
||||
*/
|
||||
|
||||
if(SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_ENABLE))
|
||||
DbgPrint("mouse.c: Failed to enable mouse!\n");
|
||||
}
|
||||
|
||||
|
||||
// Load settings from registry (by Filip Navara)
|
||||
BOOL LoadMouseSettings(PDEVICE_EXTENSION DeviceExtension, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
/*
|
||||
* Get the parameters from registry
|
||||
*/
|
||||
ULONG DefaultMouseResolution = 0;
|
||||
ULONG DisableExtensionDetection = 1;
|
||||
UNICODE_STRING ParametersPath;
|
||||
RTL_QUERY_REGISTRY_TABLE Parameters[3];
|
||||
PWSTR ParametersKeyPath = L"\\Parameters";
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlZeroMemory(Parameters, sizeof(Parameters));
|
||||
|
||||
/*
|
||||
* Formulate path to registry
|
||||
*/
|
||||
RtlInitUnicodeString(&ParametersPath, NULL);
|
||||
ParametersPath.MaximumLength = RegistryPath->Length +
|
||||
(wcslen(ParametersKeyPath) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
|
||||
ParametersPath.Buffer = ExAllocatePool(PagedPool,
|
||||
ParametersPath.MaximumLength);
|
||||
if (!ParametersPath.Buffer)
|
||||
{
|
||||
DPRINT("Can't allocate buffer for parameters\n");
|
||||
return FALSE;
|
||||
}
|
||||
RtlZeroMemory(ParametersPath.Buffer, ParametersPath.MaximumLength);
|
||||
RtlAppendUnicodeToString(&ParametersPath, RegistryPath->Buffer);
|
||||
RtlAppendUnicodeToString(&ParametersPath, ParametersKeyPath);
|
||||
DPRINT("Parameters Path: %wZ\n", &ParametersPath);
|
||||
|
||||
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[0].Name = L"Resolution";
|
||||
Parameters[0].EntryContext = &DeviceExtension->Resolution;
|
||||
Parameters[0].DefaultType = REG_DWORD;
|
||||
Parameters[0].DefaultData = &DefaultMouseResolution;
|
||||
Parameters[0].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||
Parameters[1].Name = L"DisableExtensionDetection";
|
||||
Parameters[1].EntryContext = &DeviceExtension->NoExtensions;
|
||||
Parameters[1].DefaultType = REG_DWORD;
|
||||
Parameters[1].DefaultData = &DisableExtensionDetection;
|
||||
Parameters[1].DefaultLength = sizeof(ULONG);
|
||||
|
||||
Status = RtlQueryRegistryValues(
|
||||
RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
|
||||
ParametersPath.Buffer,
|
||||
Parameters,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("RtlQueryRegistryValues failed (0x%x)\n", Status);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Initialize the PS/2 mouse support
|
||||
BOOLEAN SetupMouse(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
Millisecond_Timeout.QuadPart = -10000L;
|
||||
|
||||
/* setup */
|
||||
DeviceExtension->NoExtensions = 0;
|
||||
DeviceExtension->InputDataCount[0] = 0;
|
||||
DeviceExtension->InputDataCount[1] = 0;
|
||||
DeviceExtension->ActiveQueue = 0;
|
||||
DeviceExtension->MouseBufferPosition = 0;
|
||||
DeviceExtension->MouseBufferSize = 3;
|
||||
DeviceExtension->Resolution = 0;
|
||||
DeviceExtension->RepliesExpected = 0;
|
||||
DeviceExtension->PreviousButtons = 0;
|
||||
DeviceExtension->SmartScroll = 1;
|
||||
DeviceExtension->ack = 0;
|
||||
DeviceExtension->acking = 0;
|
||||
|
||||
LoadMouseSettings(DeviceExtension, RegistryPath);
|
||||
|
||||
// Enable the PS/2 mouse port
|
||||
controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE);
|
||||
|
||||
//InitializeMouse(DeviceExtension);
|
||||
DeviceExtension->MouseType = TestMouse(DeviceExtension);
|
||||
|
||||
if(DeviceExtension->MouseType > 0)
|
||||
{
|
||||
/* set the incoming buffer to 4 if needed */
|
||||
DeviceExtension->MouseBufferSize += (DeviceExtension->MouseType >= PSMOUSE_GENPS);
|
||||
|
||||
DPRINT("Detected Mouse: 0x%x\n", DeviceExtension->MouseType);
|
||||
|
||||
InitializeMouse(DeviceExtension);
|
||||
|
||||
// Enable controller interrupts
|
||||
mouse_write_command (MOUSE_INTERRUPTS_ON);
|
||||
|
||||
// Connect the interrupt for the mouse irq
|
||||
MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, &Dirql, &Affinity);
|
||||
|
||||
IoConnectInterrupt(&DeviceExtension->MouseInterrupt, MouseHandler, DeviceObject, NULL, MappedIrq,
|
||||
Dirql, Dirql, 0, FALSE, Affinity, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME - this fixes the crash if no mouse was detected */
|
||||
|
||||
// Connect the interrupt for the mouse irq
|
||||
MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, &Dirql, &Affinity);
|
||||
|
||||
IoConnectInterrupt(&DeviceExtension->MouseInterrupt, MouseHandler, DeviceObject, NULL, MappedIrq,
|
||||
Dirql, Dirql, 0, FALSE, Affinity, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Check if this is a dual port controller.
|
||||
BOOLEAN DetectPS2Port(void)
|
||||
{
|
||||
int loops;
|
||||
unsigned scancode;
|
||||
BOOLEAN return_value = FALSE;
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
Millisecond_Timeout.QuadPart = -10000L;
|
||||
|
||||
//return TRUE; // The rest of this code fails under BOCHs
|
||||
|
||||
/* Put the value 0x5A in the output buffer using the "WriteAuxiliary Device Output Buffer" command (0xD3).
|
||||
Poll the Status Register for a while to see if the value really turns up in the Data Register. If the
|
||||
KEYBOARD_STATUS_MOUSE_OBF bit is also set to 1 in the Status Register, we assume this controller has an
|
||||
Auxiliary Port (a.k.a. Mouse Port). */
|
||||
|
||||
controller_wait ();
|
||||
controller_write_command(CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER);
|
||||
controller_wait ();
|
||||
|
||||
/* 0x5A is a random dummy value */
|
||||
controller_write_output(0x5A);
|
||||
|
||||
for (loops = 0; loops < 10; loops++)
|
||||
{
|
||||
unsigned char status = controller_read_status();
|
||||
|
||||
if((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
scancode = controller_read_input();
|
||||
if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
|
||||
{
|
||||
return_value = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
|
||||
// CHAOS is also under the GNU General Public License.
|
||||
|
||||
#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 MOUSE_INTERRUPTS_OFF (CONTROLLER_MODE_KCC | \
|
||||
CONTROLLER_MODE_DISABLE_MOUSE | \
|
||||
CONTROLLER_MODE_SYS | \
|
||||
CONTROLLER_MODE_KEYBOARD_INTERRUPT)
|
||||
|
||||
#define MOUSE_INTERRUPTS_ON (CONTROLLER_MODE_KCC | \
|
||||
CONTROLLER_MODE_SYS | \
|
||||
CONTROLLER_MODE_MOUSE_INTERRUPT | \
|
||||
CONTROLLER_MODE_KEYBOARD_INTERRUPT)
|
||||
|
||||
// Used with mouse buttons
|
||||
#define GPM_B_LEFT 0x01
|
||||
#define GPM_B_RIGHT 0x02
|
||||
#define GPM_B_MIDDLE 0x04
|
||||
#define GPM_B_FOURTH 0x10
|
||||
#define GPM_B_FIFTH 0x20
|
||||
|
||||
// Mouse types
|
||||
#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
|
||||
|
||||
// Some aux operations take long time
|
||||
#define MAX_RETRIES 60
|
||||
|
||||
// Hardware defines
|
||||
#define MOUSE_IRQ 12
|
||||
#define MOUSE_WRAP_MASK 0x1F
|
||||
|
||||
#define MOUSE_ISINTELLIMOUSE 0x03
|
||||
#define MOUSE_ISINTELLIMOUSE5BUTTONS 0x04
|
||||
|
||||
BOOLEAN DetectPS2Port(void);
|
||||
BOOLEAN SetupMouse(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING RegistryPath);
|
||||
void controller_wait(void);
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
** PS/2 driver 0.0.2
|
||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
||||
** For ReactOS (www.reactos.com)
|
||||
|
||||
** Handles the keyboard and mouse on the PS/2 ports
|
||||
|
||||
** TODO: Fix detect_ps2_port(void) so that it works under BOCHs
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <ddk/ntddmou.h>
|
||||
#include "mouse.h"
|
||||
#include "psaux.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
static PIRP CurrentIrp;
|
||||
static ULONG MouseDataRead;
|
||||
static ULONG MouseDataRequired;
|
||||
static BOOLEAN AlreadyOpened = FALSE;
|
||||
|
||||
BOOLEAN STDCALL
|
||||
MouseSynchronizeRoutine(PVOID Context)
|
||||
{
|
||||
PIRP Irp = (PIRP)Context;
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
|
||||
|
||||
if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
|
||||
MouseDataRead=NrToRead;
|
||||
CurrentIrp=Irp;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
PS2MouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
oldIrql = KeGetCurrentIrql();
|
||||
if (oldIrql < DISPATCH_LEVEL)
|
||||
{
|
||||
KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
|
||||
IoStartNextPacket (DeviceObject, FALSE);
|
||||
KeLowerIrql(oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoStartNextPacket (DeviceObject, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (stk->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
if (AlreadyOpened == TRUE)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
AlreadyOpened = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("NOT IMPLEMENTED\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Status==STATUS_PENDING)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
BOOLEAN STDCALL PS2MouseInitializeDataQueue(PVOID Context)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS status;
|
||||
|
||||
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_INTERNAL_MOUSE_CONNECT:
|
||||
|
||||
DeviceExtension->ClassInformation =
|
||||
*((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
|
||||
|
||||
// Reinitialize the port input data queue synchronously
|
||||
KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
|
||||
PS2MouseInitializeDataQueue, DeviceExtension);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
if (status == STATUS_PENDING) {
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
} else {
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
ULONG Queue;
|
||||
|
||||
Queue = DeviceExtension->ActiveQueue % 2;
|
||||
InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue);
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
|
||||
DeviceExtension->ClassInformation.DeviceObject,
|
||||
DeviceExtension->MouseInputData[Queue],
|
||||
NULL,
|
||||
&DeviceExtension->InputDataCount[Queue]);
|
||||
DeviceExtension->InputDataCount[Queue] = 0;
|
||||
}
|
||||
|
||||
/* Maximum value plus one for \Device\PointerClass* device name */
|
||||
#define POINTER_PORTS_MAXIMUM 8
|
||||
/* Letter count for POINTER_PORTS_MAXIMUM variable * sizeof(WCHAR) */
|
||||
#define SUFFIX_MAXIMUM_SIZE (1 * sizeof(WCHAR))
|
||||
|
||||
/* This is almost the same routine as in sermouse.c. */
|
||||
STATIC PDEVICE_OBJECT
|
||||
AllocatePointerDevice(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING SuffixString;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Suffix;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Allocate buffer for full device name */
|
||||
RtlInitUnicodeString(&DeviceName, NULL);
|
||||
DeviceName.MaximumLength = sizeof(DD_MOUSE_DEVICE_NAME_U) + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
|
||||
DeviceName.Buffer = ExAllocatePool(PagedPool, DeviceName.MaximumLength);
|
||||
RtlAppendUnicodeToString(&DeviceName, DD_MOUSE_DEVICE_NAME_U);
|
||||
|
||||
/* Allocate buffer for device name suffix */
|
||||
RtlInitUnicodeString(&SuffixString, NULL);
|
||||
SuffixString.MaximumLength = SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
|
||||
SuffixString.Buffer = ExAllocatePool(PagedPool, SuffixString.MaximumLength);
|
||||
|
||||
/* Generate full qualified name with suffix */
|
||||
for (Suffix = 0; Suffix < POINTER_PORTS_MAXIMUM; ++Suffix)
|
||||
{
|
||||
ANSI_STRING DebugString;
|
||||
|
||||
RtlIntegerToUnicodeString(Suffix, 10, &SuffixString);
|
||||
RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
|
||||
// FIXME: this isn't really a serial mouse port driver
|
||||
Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
|
||||
&DeviceName, FILE_DEVICE_SERIAL_MOUSE_PORT, 0, TRUE, &DeviceObject);
|
||||
RtlUnicodeStringToAnsiString(&DebugString, &DeviceName, TRUE);
|
||||
DPRINT("%s", DebugString.Buffer);
|
||||
RtlFreeAnsiString(&DebugString);
|
||||
/* Device successfully created, leave the cyclus */
|
||||
if (NT_SUCCESS(Status))
|
||||
break;
|
||||
DeviceName.Length -= SuffixString.Length;
|
||||
}
|
||||
|
||||
ExFreePool(DeviceName.Buffer);
|
||||
ExFreePool(SuffixString.Buffer);
|
||||
|
||||
/* Couldn't create device */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
|
||||
|
||||
return DeviceObject;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
if (DetectPS2Port() == TRUE) {
|
||||
DPRINT("PS2 Port Driver version 0.0.2\n");
|
||||
} else {
|
||||
DPRINT1("PS2 port not found.\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PS2MouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl;
|
||||
DriverObject->DriverStartIo = PS2MouseStartIo;
|
||||
|
||||
DeviceObject = AllocatePointerDevice(DriverObject);
|
||||
|
||||
SetupMouse(DeviceObject, RegistryPath);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
typedef struct _DEVICE_EXTENSION {
|
||||
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
ULONG ActiveQueue;
|
||||
ULONG InputDataCount[2];
|
||||
MOUSE_INPUT_DATA MouseInputData[2][MOUSE_BUFFER_SIZE];
|
||||
|
||||
unsigned char MouseBuffer[8];
|
||||
unsigned char pkt[8];
|
||||
unsigned char MouseType;
|
||||
unsigned char MouseModel;
|
||||
unsigned char ack, acking;
|
||||
ULONG SmartScroll;
|
||||
ULONG NoExtensions;
|
||||
UINT MouseBufferPosition;
|
||||
UINT MouseBufferSize;
|
||||
UINT Resolution;
|
||||
UINT RepliesExpected;
|
||||
ULONG PreviousButtons;
|
||||
|
||||
|
||||
CLASS_INFORMATION ClassInformation;
|
||||
|
||||
PKINTERRUPT MouseInterrupt;
|
||||
KDPC IsrDpc;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
/* $Id$ */
|
||||
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "PS Auxiliary Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "psaux\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "psaux.sys\0"
|
||||
#include <reactos/version.rc>
|
|
@ -1,410 +0,0 @@
|
|||
/*
|
||||
* 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 InitSynaptics(PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* 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…
Reference in a new issue