diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index f8202f52be..6174c7f45b 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -26,9 +26,9 @@ static bool joypad_is_end_of_list(joypad_connection_t *pad) { - return pad - && !pad->connected - && !pad->iface + return pad + && !pad->connected + && !pad->iface && (pad->data == (void *)0xdeadbeef); } @@ -183,8 +183,10 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn, if (name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid)) { + RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match); s->iface = pad_map[i].iface; - s->data = s->iface->init(data, pad, driver); + s->data = data; + s->connection = s->iface->init(data, pad, driver); s->connected = true; #if 0 RARCH_LOG("%s found \n", pad_map[i].name); @@ -203,6 +205,7 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn, * set up one without an interface */ if (!s->connected) { + RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); s->iface = NULL; s->data = data; s->connected = true; @@ -219,15 +222,16 @@ void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad) if (joyconn->iface) { - joyconn->iface->set_rumble(joyconn->data, RETRO_RUMBLE_STRONG, 0); - joyconn->iface->set_rumble(joyconn->data, RETRO_RUMBLE_WEAK, 0); + joyconn->iface->set_rumble(joyconn->connection, RETRO_RUMBLE_STRONG, 0); + joyconn->iface->set_rumble(joyconn->connection, RETRO_RUMBLE_WEAK, 0); if (joyconn->iface->deinit) - joyconn->iface->deinit(joyconn->data); + joyconn->iface->deinit(joyconn->connection); } - joyconn->iface = NULL; - joyconn->connected = false; + joyconn->iface = NULL; + joyconn->connected = false; + joyconn->connection = NULL; } void pad_connection_packet(joypad_connection_t *joyconn, uint32_t pad, @@ -235,17 +239,17 @@ void pad_connection_packet(joypad_connection_t *joyconn, uint32_t pad, { if (!joyconn || !joyconn->connected) return; - if (joyconn->iface && joyconn->data && joyconn->iface->packet_handler) - joyconn->iface->packet_handler(joyconn->data, data, length); + if (joyconn->iface && joyconn->connection && joyconn->iface->packet_handler) + joyconn->iface->packet_handler(joyconn->connection, data, length); } void pad_connection_get_buttons(joypad_connection_t *joyconn, unsigned pad, input_bits_t *state) { - if (joyconn && joyconn->iface) - joyconn->iface->get_buttons(joyconn->data, state); + if (joyconn && joyconn->iface) + joyconn->iface->get_buttons(joyconn->connection, state); else - BIT256_CLEAR_ALL_PTR( state ); + BIT256_CLEAR_ALL_PTR( state ); } int16_t pad_connection_get_axis(joypad_connection_t *joyconn, @@ -253,7 +257,7 @@ int16_t pad_connection_get_axis(joypad_connection_t *joyconn, { if (!joyconn || !joyconn->iface) return 0; - return joyconn->iface->get_axis(joyconn->data, i); + return joyconn->iface->get_axis(joyconn->connection, i); } bool pad_connection_has_interface(joypad_connection_t *joyconn, unsigned pad) @@ -283,7 +287,7 @@ bool pad_connection_rumble(joypad_connection_t *joyconn, if (!joyconn->iface || !joyconn->iface->set_rumble) return false; - joyconn->iface->set_rumble(joyconn->data, effect, strength); + joyconn->iface->set_rumble(joyconn->connection, effect, strength); return true; } @@ -291,5 +295,5 @@ const char* pad_connection_get_name(joypad_connection_t *joyconn, unsigned pad) { if (!joyconn || !joyconn->iface || !joyconn->iface->get_name) return NULL; - return joyconn->iface->get_name(joyconn->data); + return joyconn->iface->get_name(joyconn->connection); } diff --git a/input/connect/joypad_connection.h b/input/connect/joypad_connection.h index 9489fe4836..0af3f8d065 100644 --- a/input/connect/joypad_connection.h +++ b/input/connect/joypad_connection.h @@ -59,6 +59,7 @@ struct joypad_connection { struct pad_connection_interface *iface; void* data; + void* connection; bool connected; }; diff --git a/input/drivers_hid/iohidmanager_hid.c b/input/drivers_hid/iohidmanager_hid.c index 2e580eed27..602391af01 100644 --- a/input/drivers_hid/iohidmanager_hid.c +++ b/input/drivers_hid/iohidmanager_hid.c @@ -33,9 +33,9 @@ typedef struct apple_input_rec { - IOHIDElementCookie cookie; - uint32_t id; - struct apple_input_rec *next; + IOHIDElementCookie cookie; + uint32_t id; + struct apple_input_rec *next; } apple_input_rec_t; typedef struct apple_hid @@ -51,14 +51,12 @@ struct iohidmanager_hid_adapter { uint32_t slot; IOHIDDeviceRef handle; + uint32_t locationId; char name[PATH_MAX_LENGTH]; apple_input_rec_t *axes; apple_input_rec_t *hats; apple_input_rec_t *buttons; uint8_t data[2048]; -#if !(defined(__ppc__) || defined(__ppc64__)) - uint32_t uniqueId; -#endif }; CFComparisonResult iohidmanager_sort_elements(const void *val1, const void *val2, void *context) @@ -234,11 +232,11 @@ static int16_t iohidmanager_hid_joypad_state( const uint32_t joyaxis = (binds[i].joyaxis != AXIS_NONE) ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis; if ( - (uint16_t)joykey != NO_BTN + (uint16_t)joykey != NO_BTN && iohidmanager_hid_joypad_button(data, port_idx, (uint16_t)joykey)) ret |= ( 1 << i); else if (joyaxis != AXIS_NONE && - ((float)abs(iohidmanager_hid_joypad_axis(data, port_idx, joyaxis)) + ((float)abs(iohidmanager_hid_joypad_axis(data, port_idx, joyaxis)) / 0x8000) > joypad_info->axis_threshold) ret |= (1 << i); } @@ -477,14 +475,29 @@ static void iohidmanager_hid_device_input_callback(void *data, IOReturn result, } } -static void iohidmanager_hid_device_remove(void *data, - IOReturn result, void* sender) +static void iohidmanager_hid_device_remove(IOHIDDeviceRef device, iohidmanager_hid_t* hid) { - struct iohidmanager_hid_adapter *adapter = - (struct iohidmanager_hid_adapter*)data; - iohidmanager_hid_t *hid = (iohidmanager_hid_t*) - hid_driver_get_data(); - + struct iohidmanager_hid_adapter *adapter = NULL; + int i; + + /*loop though the controller ports and find the device with a matching IOHINDeviceRef*/ + for (i=0; islots[i].data; + if (!a) + continue; + if (a->handle == device) + { + adapter = a; + break; + } + } + if (!adapter) + { + RARCH_LOG("Error removing device %p\n",device, hid); + return; + } + int slot = adapter->slot; if (hid && adapter && (adapter->slot < MAX_USERS)) { input_autoconfigure_disconnect(adapter->slot, adapter->name); @@ -520,6 +533,7 @@ static void iohidmanager_hid_device_remove(void *data, } free(adapter); } + RARCH_LOG("Device removed from port %d\n", slot); } static int32_t iohidmanager_hid_device_get_int_property( @@ -555,15 +569,7 @@ static uint32_t iohidmanager_hid_device_get_location_id(IOHIDDeviceRef device) CFSTR(kIOHIDLocationIDKey)); } -#if !(defined(__ppc__) || defined(__ppc64__)) -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)); -} -#endif + static void iohidmanager_hid_device_get_product_string( IOHIDDeviceRef device, char *buf, size_t len) @@ -591,21 +597,11 @@ static void iohidmanager_hid_device_add_autodetect(unsigned idx, RARCH_LOG("Port %d: %s.\n", idx, device_name); } -#if defined(__ppc__) || defined(__ppc64__) -static void iohidmanager_hid_device_add(IOHIDDeviceRef device, - iohidmanager_hid_t* hid) -#else -static void iohidmanager_hid_device_add_device( - IOHIDDeviceRef device, iohidmanager_hid_t* hid) -#endif + +static void iohidmanager_hid_device_add(IOHIDDeviceRef device, iohidmanager_hid_t* hid) { int i; - /* get device unique id */ -#if !(defined(__ppc__) || defined(__ppc64__)) - uint32_t deviceUniqueId = iohidmanager_hid_device_get_unique_id(device); -#endif - static const uint32_t axis_use_ids[11] = { kHIDUsage_GD_X, @@ -621,18 +617,22 @@ static void iohidmanager_hid_device_add_device( kHIDUsage_Sim_Brake }; -#if !(defined(__ppc__) || defined(__ppc64__)) - /* check if pad was already registered previously (by deterministic method) - * if so do not re-add the pad */ - for (i=0; islots[i].data; - if (!a) - continue; - if (a->uniqueId == deviceUniqueId) - return; - } -#endif + /* check if pad was already registered previously when the application was + started (by deterministic method). if so do not re-add the pad */ + uint32_t deviceLocationId = iohidmanager_hid_device_get_location_id(device); + for (i=0; islots[i].data; + if (!a) + continue; + if (a->locationId == deviceLocationId) + { + a->handle = device; + /* while we're not re-adding the controller, we are re-assigning the + handle so it can be removed properly upon disconnect */ + return; + } + } IOReturn ret; uint16_t dev_vid, dev_pid; @@ -654,6 +654,7 @@ static void iohidmanager_hid_device_add_device( goto error; adapter->handle = device; + adapter->locationId = deviceLocationId; ret = IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone); @@ -663,8 +664,6 @@ static void iohidmanager_hid_device_add_device( /* Move the device's run loop to this thread. */ IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); - IOHIDDeviceRegisterRemovalCallback(device, - iohidmanager_hid_device_remove, adapter); #ifndef IOS iohidmanager_hid_device_get_product_string(device, adapter->name, @@ -673,9 +672,6 @@ static void iohidmanager_hid_device_add_device( dev_vid = iohidmanager_hid_device_get_vendor_id (device); dev_pid = iohidmanager_hid_device_get_product_id (device); -#if !(defined(__ppc__) || defined(__ppc64__)) - adapter->uniqueId = deviceUniqueId; -#endif adapter->slot = pad_connection_pad_init(hid->slots, adapter->name, dev_vid, dev_pid, adapter, @@ -900,7 +896,6 @@ static void iohidmanager_hid_device_add_device( iohidmanager_hid_device_add_autodetect(adapter->slot, adapter->name, iohidmanager_hid.ident, dev_vid, dev_pid); - return; error: @@ -940,14 +935,21 @@ error: } } -#if !(defined(__ppc__) || defined(__ppc64__)) -static void iohidmanager_hid_device_add(void *data, IOReturn result, - void* sender, IOHIDDeviceRef device) + +static void iohidmanager_hid_device_matched(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); + iohidmanager_hid_t *hid = (iohidmanager_hid_t*) hid_driver_get_data(); + + iohidmanager_hid_device_add(device, hid); } -#endif +static void iohidmanager_hid_device_removed(void *data, IOReturn result, + void* sender, IOHIDDeviceRef device) +{ + iohidmanager_hid_t *hid = (iohidmanager_hid_t*) hid_driver_get_data(); + iohidmanager_hid_device_remove(device, hid); +} + static void iohidmanager_hid_append_matching_dictionary( CFMutableArrayRef array, @@ -980,7 +982,6 @@ static int iohidmanager_hid_manager_init(iohidmanager_hid_t *hid) if (!hid->ptr) return -1; - IOHIDManagerSetDeviceMatching(hid->ptr, NULL); IOHIDManagerScheduleWithRunLoop(hid->ptr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); @@ -1004,103 +1005,99 @@ static int iohidmanager_hid_manager_free(iohidmanager_hid_t *hid) 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 = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef)); - CFSetGetValues(set, (const void **) device_array); + /* 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 = (IOHIDDeviceRef*)calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(set, (const void **) device_array); CFRelease(set); + /* re order device by location id */ + typedef struct hid_list + { + IOHIDDeviceRef device; + uint32_t lid; + struct hid_list *next; + } hid_list_t; - /* re order device by location id */ - typedef struct hid_list - { - IOHIDDeviceRef device; - uint32_t lid; - struct hid_list *next; - } hid_list_t; + hid_list_t* devList = NULL; + for (long i=0; idevice = dev; + devList->lid = iohidmanager_hid_device_get_location_id(dev); + devList->next = NULL; + } + else + { + hid_list_t * devnew = (hid_list_t *)malloc(sizeof(hid_list_t)); + devnew->device = dev; + devnew->lid = iohidmanager_hid_device_get_location_id(dev); + devnew->next = NULL; - hid_list_t* devList = NULL; - for (long i=0; idevice = dev; - devList->lid = iohidmanager_hid_device_get_location_id(dev); - devList->next = NULL; - } - else - { - hid_list_t * devnew = (hid_list_t *)malloc(sizeof(hid_list_t)); - devnew->device = dev; - devnew->lid = iohidmanager_hid_device_get_location_id(dev); - devnew->next = NULL; + hid_list_t * ptr = devList; + if (devnew->lid < ptr->lid) + { + devnew->next = ptr; + devList = devnew; + } + else + { + while ( ( ptr->lid < devnew->lid ) && (ptr->next != NULL) ) + ptr = ptr->next; + devnew->next = ptr->next; + ptr->next = devnew; + } + } + } + } - hid_list_t * ptr = devList; - if (devnew->lid < ptr->lid) - { - devnew->next = ptr; - devList = devnew; - } - else - { - while ( ( ptr->lid < devnew->lid ) && (ptr->next != NULL) ) - ptr = ptr->next; - devnew->next = ptr->next; - ptr->next = devnew; - } - } - } - } + /* register devices */ + hid_list_t * ptr = devList; + while (ptr != NULL) + { - /* register devices */ - hid_list_t * ptr = devList; - while (ptr != NULL) - { -#if defined(__ppc__) || defined(__ppc64__) iohidmanager_hid_device_add(ptr->device, hid); -#else - iohidmanager_hid_device_add_device(ptr->device, hid); -#endif - //printf("%d\n",ptr->lid); - ptr = ptr->next; - free(devList); - devList = ptr; - } - free(device_array); -#if !(defined(__ppc__) || defined(__ppc64__)) - /* register call back to dynamically add device plugged when retroarch is - * running - * 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); + ptr = ptr->next; + free(devList); + devList = ptr; + } + free(device_array); - 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); + /* register call back to dynamically add device plugged when retroarch is + * running + * 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); - IOHIDManagerSetDeviceMatchingMultiple(hid->ptr, matcher); - IOHIDManagerRegisterDeviceMatchingCallback(hid->ptr, - iohidmanager_hid_device_add, 0); + 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_matched, 0); + IOHIDManagerRegisterDeviceRemovalCallback(hid->ptr,iohidmanager_hid_device_removed, 0); + + CFRelease(matcher); - CFRelease(matcher); -#endif return 0; }