/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Windows DirectInput joystick driver. * * By Eric Botcazou. * * Omar Cornut fixed it to handle a weird peculiarity of * the DirectInput joystick API. * * See readme.txt for copyright information. */ #define DIRECTINPUT_VERSION 0x0500 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" #ifndef SCAN_DEPEND #ifdef ALLEGRO_MINGW32 #undef MAKEFOURCC #endif #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif #define PREFIX_I "al-wjoy INFO: " #define PREFIX_W "al-wjoy WARNING: " #define PREFIX_E "al-wjoy ERROR: " static int joystick_dinput_init(void); static void joystick_dinput_exit(void); static int joystick_dinput_poll(void); JOYSTICK_DRIVER joystick_directx = { JOY_TYPE_DIRECTX, empty_string, empty_string, "DirectInput joystick", joystick_dinput_init, joystick_dinput_exit, joystick_dinput_poll, NULL, NULL, NULL, NULL }; struct DINPUT_JOYSTICK_INFO { WINDOWS_JOYSTICK_INFO_MEMBERS LPDIRECTINPUTDEVICE2 device; }; static LPDIRECTINPUT joystick_dinput = NULL; static struct DINPUT_JOYSTICK_INFO dinput_joystick[MAX_JOYSTICKS]; static int dinput_joy_num = 0; /* dinput_err_str: * Returns a DirectInput error string. */ #ifdef DEBUGMODE static char* dinput_err_str(long err) { static char err_str[64]; switch (err) { case DIERR_NOTACQUIRED: _al_sane_strncpy(err_str, "the device is not acquired", sizeof(err_str)); break; case DIERR_INPUTLOST: _al_sane_strncpy(err_str, "access to the device was not granted", sizeof(err_str)); break; case DIERR_INVALIDPARAM: _al_sane_strncpy(err_str, "the device does not have a selected data format", sizeof(err_str)); break; case DIERR_OTHERAPPHASPRIO: _al_sane_strncpy(err_str, "can't acquire the device in background", sizeof(err_str)); break; default: _al_sane_strncpy(err_str, "unknown error", sizeof(err_str)); } return err_str; } #else #define dinput_err_str(hr) "\0" #endif /* joystick_dinput_acquire: [window thread] * Acquires the joystick devices. */ int joystick_dinput_acquire(void) { HRESULT hr; int i; if (joystick_dinput) { for (i=0; iguidType, &GUID_XAxis, sizeof(GUID)) == 0) { joy->axis_name[0] = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_YAxis, sizeof(GUID)) == 0) { joy->axis_name[1] = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0) { joy->axis_name[2] = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->caps |= JOYCAPS_HASZ; joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0) { joy->axis_name[joy->num_axes] = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->caps |= JOYCAPS_HASR; joy->num_axes++; } else if (memcmp(&lpddoi->guidType, &GUID_Slider, sizeof(GUID)) == 0) { if (joy->caps & JOYCAPS_HASV) { /* we support at most 2 sliders */ return DIENUM_CONTINUE; } else { if (joy->caps & JOYCAPS_HASU) joy->caps |= JOYCAPS_HASV; else joy->caps |= JOYCAPS_HASU; joy->axis_name[joy->num_axes] = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_axes++; } } else if (memcmp(&lpddoi->guidType, &GUID_POV, sizeof(GUID)) == 0) { if (joy->caps & JOYCAPS_HASPOV) { /* we support at most 1 point-of-view device */ return DIENUM_CONTINUE; } else { joy->hat_name = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->caps |= JOYCAPS_HASPOV; } } else if (memcmp(&lpddoi->guidType, &GUID_Button, sizeof(GUID)) == 0) { if (joy->num_buttons == MAX_JOYSTICK_BUTTONS-1) { return DIENUM_CONTINUE; } else { joy->button_name[joy->num_buttons] = ustrdup(uconvert_ascii(lpddoi->tszName, tmp)); joy->num_buttons++; } } return DIENUM_CONTINUE; } /* joystick_enum_callback: * Helper function to find out how many joysticks we have and set them up. */ static BOOL CALLBACK joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { LPDIRECTINPUTDEVICE _dinput_device1; LPDIRECTINPUTDEVICE2 dinput_device = NULL; HRESULT hr; LPVOID temp; HWND allegro_wnd = win_get_window(); DIPROPRANGE property_range = { /* the header */ { sizeof(DIPROPRANGE), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ 0, // lMin 256 // lMax }; DIPROPDWORD property_deadzone = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ 2000, // dwData }; if (dinput_joy_num == MAX_JOYSTICKS-1) { _TRACE(PREFIX_W "The system supports more than %d joysticks\n", MAX_JOYSTICKS); return DIENUM_STOP; } /* create the DirectInput joystick device */ hr = IDirectInput_CreateDevice(joystick_dinput, &lpddi->guidInstance, &_dinput_device1, NULL); if (FAILED(hr)) goto Error; /* query the DirectInputDevice2 interface needed for the poll() method */ hr = IDirectInputDevice_QueryInterface(_dinput_device1, &IID_IDirectInputDevice2, &temp); IDirectInputDevice_Release(_dinput_device1); if (FAILED(hr)) goto Error; dinput_device = temp; /* set cooperative level */ hr = IDirectInputDevice2_SetCooperativeLevel(dinput_device, allegro_wnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if (FAILED(hr)) goto Error; /* enumerate objects available on the device */ memset(&dinput_joystick[dinput_joy_num], 0, sizeof(struct DINPUT_JOYSTICK_INFO)); hr = IDirectInputDevice2_EnumObjects(dinput_device, object_enum_callback, &dinput_joystick[dinput_joy_num], DIDFT_PSHBUTTON | DIDFT_AXIS | DIDFT_POV); if (FAILED(hr)) goto Error; /* set data format */ hr = IDirectInputDevice2_SetDataFormat(dinput_device, &c_dfDIJoystick); if (FAILED(hr)) goto Error; /* set the range of axes */ hr = IDirectInputDevice2_SetProperty(dinput_device, DIPROP_RANGE, &property_range.diph); if (FAILED(hr)) goto Error; /* set the dead zone of axes */ hr = IDirectInputDevice2_SetProperty(dinput_device, DIPROP_DEADZONE, &property_deadzone.diph); if (FAILED(hr)) goto Error; /* register this joystick */ dinput_joystick[dinput_joy_num].device = dinput_device; if (win_add_joystick((WINDOWS_JOYSTICK_INFO *)&dinput_joystick[dinput_joy_num]) != 0) return DIENUM_STOP; dinput_joy_num++; return DIENUM_CONTINUE; Error: if (dinput_device) IDirectInputDevice2_Release(dinput_device); return DIENUM_CONTINUE; } /* joystick_dinput_init: [primary thread] * Initialises the DirectInput joystick devices. */ static int joystick_dinput_init(void) { HRESULT hr; /* the DirectInput joystick interface is not part of DirectX 3 */ if (_dx_ver < 0x0500) return -1; /* get the DirectInput interface */ hr = DirectInputCreate(allegro_inst, DIRECTINPUT_VERSION, &joystick_dinput, NULL); if (FAILED(hr)) return -1; /* enumerate the joysticks attached to the system */ hr = IDirectInput_EnumDevices(joystick_dinput, DIDEVTYPE_JOYSTICK, joystick_enum_callback, NULL, DIEDFL_ATTACHEDONLY); if (FAILED(hr)) { IDirectInput_Release(joystick_dinput); return -1; } /* acquire the devices */ wnd_call_proc(joystick_dinput_acquire); return (dinput_joy_num == 0); } /* joystick_dinput_exit: [primary thread] * Shuts down the DirectInput joystick devices. */ static void joystick_dinput_exit(void) { int i, j; /* unacquire the devices */ wnd_call_proc(joystick_dinput_unacquire); /* destroy the devices */ for (i=0; i