Byebye decrepit drivers

svn path=/trunk/; revision=14938
This commit is contained in:
Alex Ionescu 2005-05-01 22:29:18 +00:00
parent 24f249ab54
commit b099687f31
19 changed files with 2 additions and 3177 deletions

View file

@ -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

View file

@ -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)

View file

@ -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);
}

View file

@ -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_

View file

@ -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>

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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];

View file

@ -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, &param, 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;
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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>

View file

@ -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

View file

@ -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 */