⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joystick_linux.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
            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 + -