mirror of
https://github.com/libretro/RetroArch
synced 2025-04-09 21:45:45 +00:00
Merge pull request #6727 from ceb33/master
fix to set hid device registration deterministic (#6497), to address issue #6640 re-adding dynamic device registration
This commit is contained in:
commit
ec8f40c833
@ -56,6 +56,7 @@ struct iohidmanager_hid_adapter
|
|||||||
apple_input_rec_t *hats;
|
apple_input_rec_t *hats;
|
||||||
apple_input_rec_t *buttons;
|
apple_input_rec_t *buttons;
|
||||||
uint8_t data[2048];
|
uint8_t data[2048];
|
||||||
|
uint32_t uniqueId;
|
||||||
};
|
};
|
||||||
|
|
||||||
CFComparisonResult iohidmanager_sort_elements(const void *val1, const void *val2, void *context)
|
CFComparisonResult iohidmanager_sort_elements(const void *val1, const void *val2, void *context)
|
||||||
@ -485,6 +486,14 @@ static uint32_t iohidmanager_hid_device_get_location_id(IOHIDDeviceRef device)
|
|||||||
CFSTR(kIOHIDLocationIDKey));
|
CFSTR(kIOHIDLocationIDKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t iohidmanager_hid_device_get_unique_id(IOHIDDeviceRef device)
|
||||||
|
{
|
||||||
|
/* osx seems to assign an unique id to each device when they are plugged in
|
||||||
|
* the id change if device is unplugged/plugged, but it's unique amongst the
|
||||||
|
* other device plugged */
|
||||||
|
return iohidmanager_hid_device_get_int_property(device,CFSTR(kIOHIDUniqueIDKey));
|
||||||
|
}
|
||||||
|
|
||||||
static void iohidmanager_hid_device_get_product_string(
|
static void iohidmanager_hid_device_get_product_string(
|
||||||
IOHIDDeviceRef device, char *buf, size_t len)
|
IOHIDDeviceRef device, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
@ -495,6 +504,9 @@ static void iohidmanager_hid_device_get_product_string(
|
|||||||
CFStringGetCString(ref, buf, len, kCFStringEncodingUTF8);
|
CFStringGetCString(ref, buf, len, kCFStringEncodingUTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void iohidmanager_hid_device_add_autodetect(unsigned idx,
|
static void iohidmanager_hid_device_add_autodetect(unsigned idx,
|
||||||
const char *device_name, const char *driver_name,
|
const char *device_name, const char *driver_name,
|
||||||
uint16_t dev_vid, uint16_t dev_pid)
|
uint16_t dev_vid, uint16_t dev_pid)
|
||||||
@ -512,10 +524,24 @@ static void iohidmanager_hid_device_add_autodetect(unsigned idx,
|
|||||||
RARCH_LOG("Port %d: %s.\n", idx, device_name);
|
RARCH_LOG("Port %d: %s.\n", idx, device_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iohidmanager_hid_device_add(void *data, IOReturn result,
|
static void iohidmanager_hid_device_add_device(IOHIDDeviceRef device, iohidmanager_hid_t* hid)
|
||||||
void *sender, IOHIDDeviceRef device)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* get device unique id */
|
||||||
|
uint32_t deviceUniqueId = iohidmanager_hid_device_get_unique_id(device);
|
||||||
|
|
||||||
|
/* check if pad was already registered previously (by deterministic method)
|
||||||
|
* if so do not re-add the pad */
|
||||||
|
for (i=0; i<MAX_USERS; i++)
|
||||||
|
{
|
||||||
|
struct iohidmanager_hid_adapter *a = hid->slots[i].data;
|
||||||
|
if (a == NULL)
|
||||||
|
continue;
|
||||||
|
if (a->uniqueId == deviceUniqueId)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IOReturn ret;
|
IOReturn ret;
|
||||||
uint16_t dev_vid, dev_pid;
|
uint16_t dev_vid, dev_pid;
|
||||||
CFArrayRef elements_raw;
|
CFArrayRef elements_raw;
|
||||||
@ -527,8 +553,6 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result,
|
|||||||
apple_input_rec_t *tmp = NULL;
|
apple_input_rec_t *tmp = NULL;
|
||||||
apple_input_rec_t *tmpButtons = NULL;
|
apple_input_rec_t *tmpButtons = NULL;
|
||||||
apple_input_rec_t *tmpAxes = NULL;
|
apple_input_rec_t *tmpAxes = NULL;
|
||||||
iohidmanager_hid_t *hid = (iohidmanager_hid_t*)
|
|
||||||
hid_driver_get_data();
|
|
||||||
struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*)
|
struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*)
|
||||||
calloc(1, sizeof(*adapter));
|
calloc(1, sizeof(*adapter));
|
||||||
|
|
||||||
@ -557,6 +581,7 @@ static void iohidmanager_hid_device_add(void *data, IOReturn result,
|
|||||||
|
|
||||||
dev_vid = iohidmanager_hid_device_get_vendor_id (device);
|
dev_vid = iohidmanager_hid_device_get_vendor_id (device);
|
||||||
dev_pid = iohidmanager_hid_device_get_product_id (device);
|
dev_pid = iohidmanager_hid_device_get_product_id (device);
|
||||||
|
adapter->uniqueId = deviceUniqueId;
|
||||||
|
|
||||||
adapter->slot = pad_connection_pad_init(hid->slots,
|
adapter->slot = pad_connection_pad_init(hid->slots,
|
||||||
adapter->name, dev_vid, dev_pid, adapter,
|
adapter->name, dev_vid, dev_pid, adapter,
|
||||||
@ -788,6 +813,14 @@ error:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void iohidmanager_hid_device_add(void *data, IOReturn result,
|
||||||
|
void* sender, IOHIDDeviceRef device)
|
||||||
|
{
|
||||||
|
iohidmanager_hid_t *hid = (iohidmanager_hid_t*) hid_driver_get_data();
|
||||||
|
iohidmanager_hid_device_add_device(device, hid);
|
||||||
|
}
|
||||||
|
|
||||||
static void iohidmanager_hid_append_matching_dictionary(
|
static void iohidmanager_hid_append_matching_dictionary(
|
||||||
CFMutableArrayRef array,
|
CFMutableArrayRef array,
|
||||||
uint32_t page, uint32_t use)
|
uint32_t page, uint32_t use)
|
||||||
@ -841,6 +874,16 @@ static int iohidmanager_hid_manager_free(iohidmanager_hid_t *hid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iohidmanager_hid_manager_set_device_matching(
|
||||||
|
iohidmanager_hid_t *hid)
|
||||||
|
{
|
||||||
|
/* deterministically add all device currently plugged when lanching retroarch
|
||||||
|
* order by location id which seems to correspond to usb port number */
|
||||||
|
CFSetRef set = IOHIDManagerCopyDevices(hid->ptr);
|
||||||
|
CFIndex num_devices = CFSetGetCount(set);
|
||||||
|
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||||
|
CFSetGetValues(set, (const void **) device_array);
|
||||||
|
|
||||||
/* re order device by location id */
|
/* re order device by location id */
|
||||||
typedef struct hid_list
|
typedef struct hid_list
|
||||||
{
|
{
|
||||||
@ -848,28 +891,85 @@ static int iohidmanager_hid_manager_free(iohidmanager_hid_t *hid)
|
|||||||
uint32_t lid;
|
uint32_t lid;
|
||||||
struct hid_list *next;
|
struct hid_list *next;
|
||||||
} hid_list_t;
|
} hid_list_t;
|
||||||
|
|
||||||
|
hid_list_t* devList = NULL;
|
||||||
|
for (long i=0; i<num_devices;i++)
|
||||||
|
{
|
||||||
|
IOHIDDeviceRef dev = device_array[i];
|
||||||
|
/* filter gamepad/joystick devices */
|
||||||
|
if ( IOHIDDeviceConformsTo(dev, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick)
|
||||||
|
|| IOHIDDeviceConformsTo(dev, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ( devList == NULL )
|
||||||
|
{
|
||||||
|
devList = (hid_list_t *)malloc(sizeof(hid_list_t));
|
||||||
|
devList->device = dev;
|
||||||
|
devList->lid = iohidmanager_hid_device_get_location_id(dev);
|
||||||
|
devList->next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hid_list_t * new = (hid_list_t *)malloc(sizeof(hid_list_t));
|
||||||
|
new->device = dev;
|
||||||
|
new->lid = iohidmanager_hid_device_get_location_id(dev);
|
||||||
|
new->next = NULL;
|
||||||
|
|
||||||
static int iohidmanager_hid_manager_set_device_matching(
|
hid_list_t * ptr = devList;
|
||||||
iohidmanager_hid_t *hid)
|
if ( new->lid < ptr->lid )
|
||||||
{
|
{
|
||||||
CFMutableArrayRef matcher = CFArrayCreateMutable(kCFAllocatorDefault, 0,
|
new->next = ptr;
|
||||||
&kCFTypeArrayCallBacks);
|
devList = new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while ( ( ptr->lid < new->lid ) && (ptr->next != NULL) )
|
||||||
|
{
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
new->next = ptr->next;
|
||||||
|
ptr->next = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!matcher)
|
/* register devices */
|
||||||
return -1;
|
hid_list_t * ptr = devList;
|
||||||
|
while (ptr != NULL)
|
||||||
|
{
|
||||||
|
iohidmanager_hid_device_add_device(ptr->device, hid);
|
||||||
|
|
||||||
|
//printf("%d\n",ptr->lid);
|
||||||
|
ptr = ptr->next;
|
||||||
|
free(devList);
|
||||||
|
devList = ptr;
|
||||||
|
}
|
||||||
|
free(device_array);
|
||||||
|
|
||||||
iohidmanager_hid_append_matching_dictionary(matcher,
|
|
||||||
kHIDPage_GenericDesktop,
|
|
||||||
kHIDUsage_GD_Joystick);
|
|
||||||
iohidmanager_hid_append_matching_dictionary(matcher,
|
|
||||||
kHIDPage_GenericDesktop,
|
|
||||||
kHIDUsage_GD_GamePad);
|
|
||||||
|
|
||||||
IOHIDManagerSetDeviceMatchingMultiple(hid->ptr, matcher);
|
/* register call back to dynamically add device plugged when retroarch is
|
||||||
IOHIDManagerRegisterDeviceMatchingCallback(hid->ptr,
|
* running
|
||||||
iohidmanager_hid_device_add, 0);
|
* those will be added after the one plugged when retroarch was launched,
|
||||||
|
* and by order they are plugged in (so not deterministic) */
|
||||||
|
CFMutableArrayRef matcher = CFArrayCreateMutable(kCFAllocatorDefault, 0,
|
||||||
|
&kCFTypeArrayCallBacks);
|
||||||
|
|
||||||
CFRelease(matcher);
|
if (!matcher)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
iohidmanager_hid_append_matching_dictionary(matcher,
|
||||||
|
kHIDPage_GenericDesktop,
|
||||||
|
kHIDUsage_GD_Joystick);
|
||||||
|
iohidmanager_hid_append_matching_dictionary(matcher,
|
||||||
|
kHIDPage_GenericDesktop,
|
||||||
|
kHIDUsage_GD_GamePad);
|
||||||
|
|
||||||
|
IOHIDManagerSetDeviceMatchingMultiple(hid->ptr, matcher);
|
||||||
|
IOHIDManagerRegisterDeviceMatchingCallback(hid->ptr,
|
||||||
|
iohidmanager_hid_device_add, 0);
|
||||||
|
|
||||||
|
CFRelease(matcher);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user