#define I_NEED_OS2_H
#define NEED_EVENTS
#include "X.h"
#include "Xproto.h"
#include "misc.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "compiler.h"
#define INCL_DOSFILEMGR
#define INCL_DOSQUEUES
#define INCL_MOU
#undef RT_FONT
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "xf86Config.h"
#include "xf86Xinput.h"
#include "xf86OSmouse.h"
#include "mipointer.h"
static signed char stateTab[11][5][3] = {
{
{ 0, 0, 0 },
{ 0, 0, 1 },
{ 0, 0, 2 },
{ 2, 0, 3 },
{ 0, 0, -1 }
},
{
{ 1, -1, 0 },
{ 0, 0, 1 },
{ 1, -1, 2 },
{ 2, 0, 3 },
{ 1, 0, 4 },
},
{
{ 3, -3, 0 },
{ 3, -3, 1 },
{ 0, 0, 2 },
{ 2, 0, 3 },
{ 3, 0, 5 },
},
{
{ -2, 0, 0 },
{ 0, 0, 7 },
{ 0, 0, 6 },
{ 0, 0, 3 },
{ 0, 0, -1 },
},
{
{ -1, 0, 0 },
{ 0, 0, 4 },
{ -1, 0, 2 },
{ 3, 0, 10 },
{ 0, 0, -1 },
},
{
{ -3, 0, 0 },
{ -3, 0, 1 },
{ 0, 0, 5 },
{ 1, 0, 10 },
{ 0, 0, -1 },
},
{
{ -2, 0, 0 },
{ -2, 0, 1 },
{ 0, 0, 6 },
{ 1, 0, 8 },
{ 0, 0, -1 },
},
{
{ -2, 0, 0 },
{ 0, 0, 7 },
{ -2, 0, 2 },
{ 3, 0, 9 },
{ 0, 0, -1 },
},
{
{ -2, -1, 0 },
{ -2, 0, 4 },
{ -1, 0, 6 },
{ 0, 0, 8 },
{ 0, 0, -1 },
},
{
{ -2, -3, 0 },
{ -3, 0, 7 },
{ -2, 0, 5 },
{ 0, 0, 9 },
{ 0, 0, -1 },
},
{
{ -1, -3, 0 },
{ -3, 0, 4 },
{ -1, 0, 5 },
{ 0, 0, 10 },
{ 0, 0, -1 },
},
};
static char reverseMap[32] = { 0, 4, 2, 6, 1, 5, 3, 7,
8, 12, 10, 14, 9, 13, 11, 15,
16, 20, 18, 22, 17, 21, 19, 23,
24, 28, 26, 30, 25, 29, 27, 31};
static char hitachMap[16] = { 0, 2, 1, 3,
8, 10, 9, 11,
4, 6, 5, 7,
12, 14, 13, 15 };
#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f])
static CARD32
buttonTimer(InputInfoPtr pInfo)
{
MouseDevPtr pMse;
int sigstate;
int id;
pMse = pInfo->private;
sigstate = xf86BlockSIGIO ();
pMse->emulate3Pending = FALSE;
if ((id = stateTab[pMse->emulateState][4][0]) != 0) {
xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
pMse->emulateState = stateTab[pMse->emulateState][4][2];
} else {
ErrorF("Got unexpected buttonTimer in state %d\n", pMse->emulateState);
}
xf86UnblockSIGIO (sigstate);
return 0;
}
static Bool
Emulate3ButtonsSoft(InputInfoPtr pInfo)
{
MouseDevPtr pMse = pInfo->private;
if (!pMse->emulate3ButtonsSoft)
return TRUE;
pMse->emulate3Buttons = FALSE;
if (pMse->emulate3Pending)
buttonTimer(pInfo);
xf86Msg(X_INFO,"3rd Button detected: disabling emulate3Button\n");
return FALSE;
}
static void MouseBlockHandler(pointer data,
struct timeval **waitTime,
pointer LastSelectMask)
{
InputInfoPtr pInfo = (InputInfoPtr) data;
MouseDevPtr pMse = (MouseDevPtr) pInfo->private;
int ms;
if (pMse->emulate3Pending)
{
ms = pMse->emulate3Expires - GetTimeInMillis ();
if (ms <= 0)
ms = 0;
AdjustWaitForDelay (waitTime, ms);
}
}
static void MouseWakeupHandler(pointer data,
int i,
pointer LastSelectMask)
{
InputInfoPtr pInfo = (InputInfoPtr) data;
MouseDevPtr pMse = (MouseDevPtr) pInfo->private;
int ms;
if (pMse->emulate3Pending)
{
ms = pMse->emulate3Expires - GetTimeInMillis ();
if (ms <= 0)
buttonTimer (pInfo);
}
}
static int
SupportedInterfaces(void)
{
return MSE_MISC;
}
static const char* internalNames[] = {
"OS2Mouse",
NULL
};
static const char**
BuiltinNames(void)
{
return internalNames;
}
static Bool
CheckProtocol(const char *protocol)
{
int i;
for (i = 0; internalNames[i]; i++)
if (xf86NameCmp(protocol, internalNames[i]) == 0)
return TRUE;
return FALSE;
}
static const char *
DefaultProtocol(void)
{
return "OS2Mouse";
}
static const char *
SetupAuto(InputInfoPtr pInfo, int *protoPara)
{
return "OS2Mouse";
}
HMOU hMouse=65535;
HEV hMouseSem;
HQUEUE hMouseQueue;
InputInfoPtr iinfoPtr;
int MouseTid;
BOOL HandleValid=FALSE;
extern BOOL SwitchedToWPS;
extern CARD32 LastSwitchTime;
void os2MouseEventThread(void* arg);
static void
os2MouseReadInput(InputInfoPtr pInfo)
{
APIRET rc;
ULONG postCount,dataLength;
PVOID dummy;
int buttons;
int state;
int i, dx,dy;
BYTE elemPriority;
REQUESTDATA requestData;
MouseDevPtr pMse = pInfo->private;
if (!HandleValid) return;
while((rc = DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem)) == 0) {
dx = requestData.ulData;
(void)DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem);
dy = requestData.ulData;
(void)DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem);
state = requestData.ulData;
(void)DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem);
if (requestData.ulData != 0xFFFFFFFF)
xf86Msg(X_ERROR,
"Unexpected mouse event tag, %d\n",
requestData.ulData);
buttons = ((state & 0x06) ? 4 : 0) |
((state & 0x18) ? 1 : 0) |
((state & 0x60) ? 2 : 0);
pMse->PostEvent(pInfo, buttons, dx, dy, 0, 0);
}
DosResetEventSem(hMouseSem,&postCount);
}
int os2MouseProc(DeviceIntPtr pPointer, int what)
{
APIRET rc = 0;
USHORT nbuttons, state;
unsigned char map[MSE_MAXBUTTONS + 1];
int i;
InputInfoPtr pInfo = pPointer->public.devicePrivate;
MouseDevPtr pMse = pInfo->private;
pMse->device = pPointer;
switch (what) {
case DEVICE_INIT:
pPointer->public.on = FALSE;
if (hMouse == 65535)
rc = MouOpen((PSZ)0, &hMouse);
if (rc != 0)
xf86Msg(X_WARNING,"%s: cannot open mouse, rc=%d\n",
pInfo->name,rc);
else {
pInfo->fd = hMouse;
MouFlushQue(hMouse);
rc = MouGetNumButtons(&nbuttons, hMouse);
if (rc == 0)
xf86Msg(X_INFO,"%s: Mouse has %d button(s).\n",
pInfo->name,nbuttons);
if (nbuttons==2) nbuttons++;
for (i = 1; i<=nbuttons; i++)
map[i] = i;
InitPointerDeviceStruct((DevicePtr)pPointer, map, nbuttons,
miPointerGetMotionEvents, pMse->Ctrl,
miPointerGetMotionBufferSize());
xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1);
xf86InitValuatorDefaults(pPointer, 0);
InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1);
xf86InitValuatorDefaults(pPointer, 1);
xf86MotionHistoryAllocate(pInfo);
if (!HandleValid) {
rc = DosCreateEventSem(NULL,&hMouseSem,DC_SEM_SHARED,TRUE);
if (rc != 0)
xf86Msg(X_ERROR,"%s: could not create mouse queue semaphore, rc=%d\n",
pInfo->name,rc);
MouseTid = _beginthread(os2MouseEventThread,NULL,0x4000,(void *)pInfo);
xf86Msg(X_INFO,
"%s: Started Mouse event thread, Tid=%d\n",
pInfo->name, MouseTid);
DosSetPriority(2,3,0,MouseTid);
}
HandleValid=TRUE;
}
break;
case DEVICE_ON:
if (!HandleValid) return -1;
pMse->lastButtons = 0;
pMse->emulateState = 0;
pPointer->public.on = TRUE;
state = 0x300;
rc = MouSetDevStatus(&state,hMouse);
state = 0x7f;
rc = MouSetEventMask(&state,hMouse);
MouFlushQue(hMouse);
if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft)
{
RegisterBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
(pointer) pInfo);
}
break;
case DEVICE_CLOSE:
case DEVICE_OFF:
if (!HandleValid) return -1;
if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft)
{
RemoveBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
(pointer) pInfo);
}
pPointer->public.on = FALSE;
state = 0x300;
MouSetDevStatus(&state,hMouse);
state = 0;
MouSetEventMask(&state,hMouse);
if (what == DEVICE_CLOSE) {
#if 0
MouClose(hMouse);
hMouse = 65535;
pInfo->fd = -1;
HandleValid = FALSE;
#endif
}
break;
}
return Success;
}
int os2MouseQueueQuery()
{
ULONG numElements,postCount;
if (!HandleValid) return(1);
DosResetEventSem(hMouseSem,&postCount);
(void)DosQueryQueue(hMouseQueue,&numElements);
if (numElements>0) {
return 0;
}
return 1;
}
void os2MouseEventThread(void *arg)
{
APIRET rc;
MOUEVENTINFO mev;
ULONG queueParam;
USHORT waitflg;
char queueName[128];
MouseDevPtr pMse;
iinfoPtr = (InputInfoPtr)arg;
pMse = iinfoPtr->private;
sprintf(queueName,"\\QUEUES\\XF86MOU\\%d",getpid());
rc = DosCreateQueue(&hMouseQueue,0L,queueName);
xf86Msg(X_INFO,"Mouse Queue created, rc=%d\n",rc);
(void)DosPurgeQueue(hMouseQueue);
while(1) {
waitflg = 1;
rc = MouReadEventQue(&mev,&waitflg,hMouse);
if (rc) {
xf86Msg(X_ERROR,
"Bad return code from mouse driver, rc=%d\n",
rc);
xf86Msg(X_ERROR,"Mouse aborting!\n");
break;
}
queueParam = mev.col;
if ((rc = DosWriteQueue(hMouseQueue,queueParam,0L,NULL,0L)))
break;
queueParam = mev.row;
if ((rc = DosWriteQueue(hMouseQueue,queueParam,0L,NULL,0L)))
break;
queueParam = mev.fs;
if ((rc = DosWriteQueue(hMouseQueue,queueParam,0L,NULL,0L)))
break;
queueParam = 0xFFFFFFFF;
if ((rc = DosWriteQueue(hMouseQueue,queueParam,0L,NULL,0L)))
break;
}
xf86Msg(X_ERROR,
"An unrecoverable error in mouse queue has occured, rc=%d. Mouse is shutting down.\n",
rc);
DosCloseQueue(hMouseQueue);
}
static Bool
os2MousePreInit(InputInfoPtr pInfo, const char* protocol, int flags)
{
MouseDevPtr pMse = pInfo->private;
pMse->protocol = protocol;
xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
xf86CollectInputOptions(pInfo, NULL, NULL);
xf86ProcessCommonOptions(pInfo, pInfo->options);
pMse->CommonOptions(pInfo);
pInfo->device_control = os2MouseProc;
pInfo->read_input = os2MouseReadInput;
pInfo->flags |= XI86_CONFIGURED;
return TRUE;
}
OSMouseInfoPtr
xf86OSMouseInit(int flags)
{
OSMouseInfoPtr p;
p = xcalloc(sizeof(OSMouseInfoRec), 1);
if (!p)
return NULL;
p->SupportedInterfaces = SupportedInterfaces;
p->BuiltinNames = BuiltinNames;
p->DefaultProtocol = DefaultProtocol;
p->CheckProtocol = CheckProtocol;
p->PreInit = os2MousePreInit;
p->SetupAuto = SetupAuto;
return p;
}
void xf86OsMouseEvents()
{
APIRET rc;
ULONG postCount,dataLength;
PVOID dummy;
int buttons;
int state;
int i, dx,dy;
BYTE elemPriority;
REQUESTDATA requestData;
MouseDevPtr pMse = iinfoPtr->private;
if (!HandleValid) return;
while((rc = DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem)) == 0) {
dx = requestData.ulData;
(void)DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem);
dy = requestData.ulData;
(void)DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem);
state = requestData.ulData;
(void)DosReadQueue(hMouseQueue,
&requestData,&dataLength,&dummy,
0L,1L,&elemPriority,hMouseSem);
if (requestData.ulData != 0xFFFFFFFF)
xf86Msg(X_ERROR,
"Unexpected mouse event tag, %d\n",
requestData.ulData);
buttons = ((state & 0x06) ? 4 : 0) |
((state & 0x18) ? 1 : 0) |
((state & 0x60) ? 2 : 0);
pMse->PostEvent(iinfoPtr, buttons, dx, dy, 0, 0);
}
DosResetEventSem(hMouseSem,&postCount);
}