📄 joystick_linux.c
字号:
This->js.rgdwPOV[index] = 31500;
else if (This->povs[index].lY > 49150)
This->js.rgdwPOV[index] = 22500;
else
This->js.rgdwPOV[index] = 27000;
} else if (This->povs[index].lX > 49150) {
if (This->povs[index].lY < 16384)
This->js.rgdwPOV[index] = 4500;
else if (This->povs[index].lY > 49150)
This->js.rgdwPOV[index] = 13500;
else
This->js.rgdwPOV[index] = 9000;
} else {
if (This->povs[index].lY < 16384)
This->js.rgdwPOV[index] = 0;
else if (This->povs[index].lY > 49150)
This->js.rgdwPOV[index] = 18000;
else
This->js.rgdwPOV[index] = -1;
}
return This->js.rgdwPOV[index];
}
static void joy_polldev(JoystickImpl *This) {
struct timeval tv;
fd_set readfds;
struct js_event jse;
TRACE("(%p)\n", This);
if (This->joyfd==-1) {
WARN("no device\n");
return;
}
while (1) {
memset(&tv,0,sizeof(tv));
FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
return;
/* we have one event, so we can read */
if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
return;
}
TRACE("js_event: type 0x%x, number %d, value %d\n",
jse.type,jse.number,jse.value);
if (jse.type & JS_EVENT_BUTTON) {
int offset = This->offsets[jse.number + 12];
int value = jse.value?0x80:0x00;
This->js.rgbButtons[jse.number] = value;
GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
} else if (jse.type & JS_EVENT_AXIS) {
int number = This->axis_map[jse.number]; /* wine format object index */
if (number < 12) {
int offset = This->offsets[number];
int index = offset_to_object(This, offset);
LONG value = map_axis(This, jse.value, index);
/* FIXME do deadzone and saturation here */
TRACE("changing axis %d => %d\n", jse.number, number);
switch (number) {
case 0:
This->js.lX = value;
break;
case 1:
This->js.lY = value;
break;
case 2:
This->js.lZ = value;
break;
case 3:
This->js.lRx = value;
break;
case 4:
This->js.lRy = value;
break;
case 5:
This->js.lRz = value;
break;
case 6:
This->js.rglSlider[0] = value;
break;
case 7:
This->js.rglSlider[1] = value;
break;
case 8:
/* FIXME don't go off array */
if (This->axis_map[jse.number + 1] == number)
This->povs[0].lX = value;
else if (This->axis_map[jse.number - 1] == number)
This->povs[0].lY = value;
value = calculate_pov(This, 0);
break;
case 9:
if (This->axis_map[jse.number + 1] == number)
This->povs[1].lX = value;
else if (This->axis_map[jse.number - 1] == number)
This->povs[1].lY = value;
value = calculate_pov(This, 1);
break;
case 10:
if (This->axis_map[jse.number + 1] == number)
This->povs[2].lX = value;
else if (This->axis_map[jse.number - 1] == number)
This->povs[2].lY = value;
value = calculate_pov(This, 2);
break;
case 11:
if (This->axis_map[jse.number + 1] == number)
This->povs[3].lX = value;
else if (This->axis_map[jse.number - 1] == number)
This->povs[3].lY = value;
value = calculate_pov(This, 3);
break;
}
GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
} else
WARN("axis %d not supported\n", number);
}
}
}
/******************************************************************************
* GetDeviceState : returns the "state" of the joystick.
*
*/
static HRESULT WINAPI JoystickAImpl_GetDeviceState(
LPDIRECTINPUTDEVICE8A iface,
DWORD len,
LPVOID ptr)
{
JoystickImpl *This = (JoystickImpl *)iface;
TRACE("(%p,0x%08lx,%p)\n",This,len,ptr);
if (!This->acquired) {
WARN("not acquired\n");
return DIERR_NOTACQUIRED;
}
/* update joystick state */
joy_polldev(This);
/* convert and copy data to user supplied buffer */
fill_DataFormat(ptr, &This->js, This->transform);
return DI_OK;
}
/******************************************************************************
* GetDeviceData : gets buffered input data.
*/
static HRESULT WINAPI JoystickAImpl_GetDeviceData(
LPDIRECTINPUTDEVICE8A iface,
DWORD dodsize,
LPDIDEVICEOBJECTDATA dod,
LPDWORD entries,
DWORD flags)
{
JoystickImpl *This = (JoystickImpl *)iface;
DWORD len;
int nqtail;
HRESULT hr = DI_OK;
TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
if (!This->acquired) {
WARN("not acquired\n");
return DIERR_NOTACQUIRED;
}
EnterCriticalSection(&(This->crit));
joy_polldev(This);
len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
+ (This->queue_head - This->queue_tail);
if (len > *entries)
len = *entries;
if (dod == NULL) {
if (len)
TRACE("Application discarding %ld event(s).\n", len);
*entries = len;
nqtail = This->queue_tail + len;
while (nqtail >= This->queue_len)
nqtail -= This->queue_len;
} else {
if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) {
ERR("Wrong structure size !\n");
LeaveCriticalSection(&(This->crit));
return DIERR_INVALIDPARAM;
}
if (len)
TRACE("Application retrieving %ld event(s).\n", len);
*entries = 0;
nqtail = This->queue_tail;
while (len) {
/* Copy the buffered data into the application queue */
memcpy((char *)dod + *entries * dodsize, This->data_queue + nqtail, dodsize);
/* Advance position */
nqtail++;
if (nqtail >= This->queue_len)
nqtail -= This->queue_len;
(*entries)++;
len--;
}
}
if (This->overflow) {
hr = DI_BUFFEROVERFLOW;
if (!(flags & DIGDD_PEEK)) {
This->overflow = FALSE;
}
}
if (!(flags & DIGDD_PEEK))
This->queue_tail = nqtail;
LeaveCriticalSection(&(This->crit));
return hr;
}
static int find_property(JoystickImpl * This, LPCDIPROPHEADER ph)
{
int i;
if (ph->dwHow == DIPH_BYOFFSET) {
return offset_to_object(This, ph->dwObj);
} else if (ph->dwHow == DIPH_BYID) {
for (i = 0; i < This->user_df->dwNumObjs; i++) {
if ((This->user_df->rgodf[i].dwType & 0x00ffffff) == (ph->dwObj & 0x00ffffff)) {
return i;
}
}
}
return -1;
}
/******************************************************************************
* SetProperty : change input device properties
*/
static HRESULT WINAPI JoystickAImpl_SetProperty(
LPDIRECTINPUTDEVICE8A iface,
REFGUID rguid,
LPCDIPROPHEADER ph)
{
JoystickImpl *This = (JoystickImpl *)iface;
int i;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
if (ph == NULL) {
WARN("invalid parameter: ph == NULL\n");
return DIERR_INVALIDPARAM;
}
if (TRACE_ON(dinput))
_dump_DIPROPHEADER(ph);
if (!HIWORD(rguid)) {
switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
TRACE("buffersize = %ld\n",pd->dwData);
if (This->data_queue)
This->data_queue = HeapReAlloc(GetProcessHeap(),0, This->data_queue, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
else
This->data_queue = HeapAlloc(GetProcessHeap(),0, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
This->queue_head = 0;
This->queue_tail = 0;
This->queue_len = pd->dwData;
break;
}
case (DWORD)DIPROP_RANGE: {
LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
if (ph->dwHow == DIPH_DEVICE) {
TRACE("proprange(%ld,%ld) all\n",pr->lMin,pr->lMax);
for (i = 0; i < This->user_df->dwNumObjs; i++) {
This->props[i].lMin = pr->lMin;
This->props[i].lMax = pr->lMax;
}
} else {
int obj = find_property(This, ph);
TRACE("proprange(%ld,%ld) obj=%d\n",pr->lMin,pr->lMax,obj);
if (obj >= 0) {
This->props[obj].lMin = pr->lMin;
This->props[obj].lMax = pr->lMax;
return DI_OK;
}
}
break;
}
case (DWORD)DIPROP_DEADZONE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
if (ph->dwHow == DIPH_DEVICE) {
TRACE("deadzone(%ld) all\n",pd->dwData);
for (i = 0; i < This->user_df->dwNumObjs; i++)
This->props[i].lDeadZone = pd->dwData;
} else {
int obj = find_property(This, ph);
TRACE("deadzone(%ld) obj=%d\n",pd->dwData,obj);
if (obj >= 0) {
This->props[obj].lDeadZone = pd->dwData;
return DI_OK;
}
}
break;
}
case (DWORD)DIPROP_SATURATION: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
if (ph->dwHow == DIPH_DEVICE) {
TRACE("saturation(%ld) all\n",pd->dwData);
for (i = 0; i < This->user_df->dwNumObjs; i++)
This->props[i].lSaturation = pd->dwData;
} else {
int obj = find_property(This, ph);
TRACE("saturation(%ld) obj=%d\n",pd->dwData,obj);
if (obj >= 0) {
This->props[obj].lSaturation = pd->dwData;
return DI_OK;
}
}
break;
}
default:
FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
return DI_OK;
}
/******************************************************************************
* SetEventNotification : specifies event to be sent on state change
*/
static HRESULT WINAPI JoystickAImpl_SetEventNotification(
LPDIRECTINPUTDEVICE8A iface, HANDLE hnd
) {
JoystickImpl *This = (JoystickImpl *)iface;
TRACE("(this=%p,%p)\n",This,hnd);
This->hEvent = hnd;
return DI_OK;
}
static HRESULT WINAPI JoystickAImpl_GetCapabilities(
LPDIRECTINPUTDEVICE8A iface,
LPDIDEVCAPS lpDIDevCaps)
{
JoystickImpl *This = (JoystickImpl *)iface;
int size;
TRACE("%p->(%p)\n",iface,lpDIDevCaps);
if (lpDIDevCaps == NULL) {
WARN("invalid pointer\n");
return E_POINTER;
}
size = lpDIDevCaps->dwSize;
if (!(size == sizeof(DIDEVCAPS) || size == sizeof(DIDEVCAPS_DX3))) {
WARN("invalid parameter\n");
return DIERR_INVALIDPARAM;
}
CopyMemory(lpDIDevCaps, &This->devcaps, size);
lpDIDevCaps->dwSize = size;
if (TRACE_ON(dinput))
_dump_DIDEVCAPS(lpDIDevCaps);
return DI_OK;
}
static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
{
JoystickImpl *This = (JoystickImpl *)iface;
TRACE("(%p)\n",This);
if (!This->acquired) {
WARN("not acquired\n");
return DIERR_NOTACQUIRED;
}
joy_polldev(This);
return DI_OK;
}
/******************************************************************************
* EnumObjects : enumerate the different buttons and axis...
*/
static HRESULT WINAPI JoystickAImpl_EnumObjects(
LPDIRECTINPUTDEVICE8A iface,
LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
LPVOID lpvRef,
DWORD dwFlags)
{
JoystickImpl *This = (JoystickImpl *)iface;
DIDEVICEOBJECTINSTANCEA ddoi;
BYTE i;
int user_offset;
int user_object;
TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
if (TRACE_ON(dinput)) {
TRACE(" - flags = ");
_dump_EnumObjects_flags(dwFlags);
TRACE("\n");
}
/* Only the fields till dwFFMaxForce are relevant */
ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
/* For the joystick, do as is done in the GetCapabilities function */
if ((dwFlags == DIDFT_ALL) ||
(dwFlags & DIDFT_AXIS) ||
(dwFlags & DIDFT_POV)) {
int pov[4] = { 0, 0, 0, 0 };
int axes = 0;
int povs = 0;
for (i = 0; i < This->axes; i++) {
int wine_obj = This->axis_map[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -