[DINPUT] Sync with Wine Staging 1.9.16. CORE-11866

svn path=/trunk/; revision=72264
This commit is contained in:
Amine Khaldi 2016-08-18 09:43:58 +00:00
parent db110c2bfe
commit 9311bf01ef
5 changed files with 175 additions and 15 deletions

View file

@ -512,7 +512,7 @@ failed:
return DIERR_OUTOFMEMORY;
}
/* find an object by it's offset in a data format */
/* find an object by its offset in a data format */
static int offset_to_object(const DataFormat *df, int offset)
{
int i;

View file

@ -57,10 +57,13 @@ struct JoyDev
{
char device[MAX_PATH];
char name[MAX_PATH];
GUID guid_product;
BYTE axis_count;
BYTE button_count;
int *dev_axes_map;
WORD vendor_id, product_id;
};
typedef struct JoystickImpl JoystickImpl;
@ -100,6 +103,19 @@ static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903
{0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
};
/*
* Construct the GUID in the same way of Windows doing this.
* Data1 is concatenation of productid and vendorid.
* Data2 and Data3 are NULL.
* Data4 seems to be a constant.
*/
static const GUID DInput_Wine_Joystick_Constant_Part_GUID = {
0x000000000,
0x0000,
0x0000,
{0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
};
#define MAX_JOYSTICKS 64
static INT joystick_devices_count = -1;
static struct JoyDev *joystick_devices;
@ -115,9 +131,10 @@ static INT find_joystick_devices(void)
joystick_devices_count = 0;
for (i = 0; i < MAX_JOYSTICKS; i++)
{
int fd;
int fd, sys_fd;
struct JoyDev joydev, *new_joydevs;
BYTE axes_map[ABS_MAX + 1];
char sys_path[sizeof("/sys/class/input/js/device/id/product") + 10], id_str[5];
snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i);
if ((fd = open(joydev.device, O_RDONLY)) < 0)
@ -184,6 +201,47 @@ static INT find_joystick_devices(void)
joydev.dev_axes_map[j] = -1;
}
/* Find vendor_id and product_id in sysfs */
joydev.vendor_id = 0;
joydev.product_id = 0;
sprintf(sys_path, "/sys/class/input/js%d/device/id/vendor", i);
sys_fd = open(sys_path, O_RDONLY);
if (sys_fd > 0)
{
if (read(sys_fd, id_str, 4) == 4)
{
id_str[4] = '\0';
joydev.vendor_id = strtol(id_str, NULL, 16);
}
close(sys_fd);
}
sprintf(sys_path, "/sys/class/input/js%d/device/id/product", i);
sys_fd = open(sys_path, O_RDONLY);
if (sys_fd > 0)
{
if (read(sys_fd, id_str, 4) == 4)
{
id_str[4] = '\0';
joydev.product_id = strtol(id_str, NULL, 16);
}
close(sys_fd);
}
if (joydev.vendor_id == 0 || joydev.product_id == 0)
{
joydev.guid_product = DInput_Wine_Joystick_GUID;
}
else
{
/* Concatenate product_id with vendor_id to mimic Windows behaviour */
joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID;
joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id);
}
close(fd);
if (!joystick_devices_count)
@ -214,7 +272,7 @@ static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD ver
lpddi->dwSize = dwSize;
lpddi->guidInstance = DInput_Wine_Joystick_GUID;
lpddi->guidInstance.Data3 = id;
lpddi->guidProduct = DInput_Wine_Joystick_GUID;
lpddi->guidProduct = joystick_devices[id].guid_product;
/* we only support traditional joysticks for now */
if (version >= 0x0800)
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
@ -237,7 +295,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
lpddi->dwSize = dwSize;
lpddi->guidInstance = DInput_Wine_Joystick_GUID;
lpddi->guidInstance.Data3 = id;
lpddi->guidProduct = DInput_Wine_Joystick_GUID;
lpddi->guidProduct = joystick_devices[id].guid_product;
/* we only support traditional joysticks for now */
if (version >= 0x0800)
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);

View file

@ -77,6 +77,7 @@ struct JoyDev {
char *device;
char *name;
GUID guid;
GUID guid_product;
BOOL has_ff;
int num_effects;
@ -142,6 +143,19 @@ static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a-
{0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
};
/*
* Construct the GUID in the same way of Windows doing this.
* Data1 is concatenation of productid and vendorid.
* Data2 and Data3 are NULL.
* Data4 seems to be a constant.
*/
static const GUID DInput_Wine_Joystick_Constant_Part_GUID = {
0x000000000,
0x0000,
0x0000,
{0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
};
#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
#define MAX_JOYDEV 64
@ -274,11 +288,18 @@ static void find_joydevs(void)
}
if (ioctl(fd, EVIOCGID, &device_id) == -1)
{
WARN("ioctl(EVIOCGID) failed: %d %s\n", errno, strerror(errno));
joydev.guid_product = DInput_Wine_Joystick_Base_GUID;
}
else
{
joydev.vendor_id = device_id.vendor;
joydev.product_id = device_id.product;
/* Concatenate product_id with vendor_id to mimic Windows behaviour */
joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID;
joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id);
}
if (!have_joydevs)
@ -308,7 +329,7 @@ static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD ver
lpddi->dwSize = dwSize;
lpddi->guidInstance = joydevs[id].guid;
lpddi->guidProduct = DInput_Wine_Joystick_Base_GUID;
lpddi->guidProduct = joydevs[id].guid_product;
lpddi->guidFFDriver = GUID_NULL;
if (version >= 0x0800)
@ -329,7 +350,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
lpddi->dwSize = dwSize;
lpddi->guidInstance = joydevs[id].guid;
lpddi->guidProduct = DInput_Wine_Joystick_Base_GUID;
lpddi->guidProduct = joydevs[id].guid_product;
lpddi->guidFFDriver = GUID_NULL;
if (version >= 0x0800)

View file

@ -175,9 +175,86 @@ static HRESULT osx_to_win32_hresult(HRESULT in)
return in;
}
static void CFSetApplierFunctionCopyToCFArray(const void *value, void *context)
static long get_device_property_long(IOHIDDeviceRef device, CFStringRef key)
{
CFArrayAppendValue( ( CFMutableArrayRef ) context, value );
CFTypeRef ref;
long result = 0;
if (device)
{
assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device));
ref = IOHIDDeviceGetProperty(device, key);
if (ref && CFNumberGetTypeID() == CFGetTypeID(ref))
CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &result);
}
return result;
}
static CFStringRef copy_device_name(IOHIDDeviceRef device)
{
CFStringRef name;
if (device)
{
CFTypeRef ref_name;
assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device));
ref_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
if (ref_name && CFStringGetTypeID() == CFGetTypeID(ref_name))
name = CFStringCreateCopy(kCFAllocatorDefault, ref_name);
else
{
long vendID, prodID;
vendID = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
prodID = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%04lx 0x%04lx"), vendID, prodID);
}
}
else
{
ERR("NULL device\n");
name = CFStringCreateCopy(kCFAllocatorDefault, CFSTR(""));
}
return name;
}
static long get_device_location_ID(IOHIDDeviceRef device)
{
return get_device_property_long(device, CFSTR(kIOHIDLocationIDKey));
}
static void copy_set_to_array(const void *value, void *context)
{
CFArrayAppendValue(context, value);
}
static CFComparisonResult device_name_comparator(IOHIDDeviceRef device1, IOHIDDeviceRef device2)
{
CFStringRef name1 = copy_device_name(device1), name2 = copy_device_name(device2);
CFComparisonResult result = CFStringCompare(name1, name2, (kCFCompareForcedOrdering | kCFCompareNumerically));
CFRelease(name1);
CFRelease(name2);
return result;
}
static CFComparisonResult device_location_name_comparator(const void *val1, const void *val2, void *context)
{
IOHIDDeviceRef device1 = (IOHIDDeviceRef)val1, device2 = (IOHIDDeviceRef)val2;
long loc1 = get_device_location_ID(device1), loc2 = get_device_location_ID(device2);
if (loc1 < loc2)
return kCFCompareLessThan;
else if (loc1 > loc2)
return kCFCompareGreaterThan;
/* virtual joysticks may not have a kIOHIDLocationIDKey and will default to location ID of 0, this orders virtual joysticks by their name */
return device_name_comparator(device1, device2);
}
static const char* debugstr_cf(CFTypeRef t)
@ -212,8 +289,9 @@ static const char* debugstr_cf(CFTypeRef t)
static const char* debugstr_device(IOHIDDeviceRef device)
{
return wine_dbg_sprintf("<IOHIDDevice %p product %s>", device,
debugstr_cf(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))));
return wine_dbg_sprintf("<IOHIDDevice %p product %s IOHIDLocationID %lu>", device,
debugstr_cf(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))),
get_device_location_ID(device));
}
static const char* debugstr_element(IOHIDElementRef element)
@ -449,10 +527,13 @@ static int find_osx_devices(void)
if (devset)
{
CFIndex num_devices, num_main_elements, idx;
CFMutableArrayRef devices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, devices);
CFRelease( devset);
num_devices = CFArrayGetCount(devices);
CFMutableArrayRef devices;
num_devices = CFSetGetCount(devset);
devices = CFArrayCreateMutable(kCFAllocatorDefault, num_devices, &kCFTypeArrayCallBacks);
CFSetApplyFunction(devset, copy_set_to_array, devices);
CFRelease(devset);
CFArraySortValues(devices, CFRangeMake(0, num_devices), device_location_name_comparator, NULL);
device_main_elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if (!device_main_elements)

View file

@ -30,7 +30,7 @@ reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-1.9.4
reactos/dll/directx/wine/d3dxof # Synced to WineStaging-1.9.16
reactos/dll/directx/wine/ddraw # Synced to WineStaging-1.9.4
reactos/dll/directx/wine/devenum # Synced to WineStaging-1.9.16
reactos/dll/directx/wine/dinput # Synced to WineStaging-1.9.11
reactos/dll/directx/wine/dinput # Synced to WineStaging-1.9.16
reactos/dll/directx/wine/dinput8 # Synced to WineStaging-1.9.11
reactos/dll/directx/wine/dmusic # Synced to WineStaging-1.9.11
reactos/dll/directx/wine/dplay # Synced to WineStaging-1.9.11