diff --git a/apple/OSX/platform.m b/apple/OSX/platform.m index 6eced1262f..eaa84eb1db 100644 --- a/apple/OSX/platform.m +++ b/apple/OSX/platform.m @@ -194,9 +194,6 @@ static char** waiting_argv; _wantReload = false; apple_start_iteration(); - - extern void osx_pad_init(); - osx_pad_init(); } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication diff --git a/input/apple_hid_pad.c b/input/apple_hid_pad.c deleted file mode 100644 index 2e92418ded..0000000000 --- a/input/apple_hid_pad.c +++ /dev/null @@ -1,176 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2013-2014 - Jason Fetters - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include -#include "apple_input.h" - -struct apple_pad_connection -{ - uint32_t slot; - IOHIDDeviceRef device; - uint8_t data[2048]; -}; - -static IOHIDManagerRef g_hid_manager; - -void apple_pad_send_control(struct apple_pad_connection* connection, uint8_t* data, size_t size) -{ - IOHIDDeviceSetReport(connection->device, kIOHIDReportTypeOutput, 0x01, data + 1, size - 1); -} - -// NOTE: I pieced this together through trial and error, any corrections are welcome -static void hid_device_input_callback(void* context, IOReturn result, void* sender, IOHIDValueRef value) -{ - IOHIDElementRef element; - uint32_t type, page, use; - struct apple_pad_connection* connection = (struct apple_pad_connection*)context; - - element = IOHIDValueGetElement(value); - type = IOHIDElementGetType(element); - page = IOHIDElementGetUsagePage(element); - use = IOHIDElementGetUsage(element); - - // Joystick handler: TODO: Can GamePad work the same? - if (type == kIOHIDElementTypeInput_Button && page == kHIDPage_Button) - { - CFIndex state = IOHIDValueGetIntegerValue(value); - - if (state) - g_current_input_data.pad_buttons[connection->slot] |= (1 << (use - 1)); - else - g_current_input_data.pad_buttons[connection->slot] &= ~(1 << (use - 1)); - } - else if (type == kIOHIDElementTypeInput_Misc && page == kHIDPage_GenericDesktop) - { - static const uint32_t axis_use_ids[4] = { 48, 49, 50, 53 }; - int i; - - for (i = 0; i < 4; i ++) - { - if (use == axis_use_ids[i]) - { - CFIndex min, max, state; - float val; - - min = IOHIDElementGetPhysicalMin(element); - max = IOHIDElementGetPhysicalMax(element) - min; - state = IOHIDValueGetIntegerValue(value) - min; - - val = (float)state / (float)max; - g_current_input_data.pad_axis[connection->slot][i] = ((val * 2.0f) - 1.0f) * 32767.0f; - } - } - } -} - -static void hid_device_removed(void* context, IOReturn result, void* sender) -{ - struct apple_pad_connection* connection = (struct apple_pad_connection*)context; - - if (connection && connection->slot < MAX_PLAYERS) - { - g_current_input_data.pad_buttons[connection->slot] = 0; - memset(g_current_input_data.pad_axis[connection->slot], 0, sizeof(g_current_input_data.pad_axis)); - - apple_joypad_disconnect(connection->slot); - free(connection); - } - - IOHIDDeviceClose(sender, kIOHIDOptionsTypeNone); -} - -static void hid_device_report(void* context, IOReturn result, void *sender, IOHIDReportType type, uint32_t reportID, uint8_t *report, CFIndex reportLength) -{ - struct apple_pad_connection* connection = (struct apple_pad_connection*)context; - apple_joypad_packet(connection->slot, connection->data, reportLength + 1); -} - -static void hid_manager_device_attached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) -{ - char device_name[1024]; - CFStringRef device_name_ref; - struct apple_pad_connection* connection = calloc(1, sizeof(struct apple_pad_connection)); - - connection->device = device; - connection->slot = MAX_PLAYERS; - - IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone); - IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); - IOHIDDeviceRegisterRemovalCallback(device, hid_device_removed, connection); - - device_name_ref = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); - CFStringGetCString(device_name_ref, device_name, sizeof(device_name), kCFStringEncodingUTF8); - - connection->slot = apple_joypad_connect(device_name, connection); - - if (apple_joypad_has_interface(connection->slot)) - IOHIDDeviceRegisterInputReportCallback(device, connection->data + 1, sizeof(connection->data) - 1, hid_device_report, connection); - else - IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection); -} - -static void append_matching_dictionary(CFMutableArrayRef array, uint32_t page, uint32_t use) -{ - CFNumberRef pagen, usen; - CFMutableDictionaryRef matcher; - - matcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - pagen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); - CFDictionarySetValue(matcher, CFSTR(kIOHIDDeviceUsagePageKey), pagen); - CFRelease(pagen); - - usen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &use); - CFDictionarySetValue(matcher, CFSTR(kIOHIDDeviceUsageKey), usen); - CFRelease(usen); - - CFArrayAppendValue(array, matcher); - CFRelease(matcher); -} - -void osx_pad_init(void) -{ - CFMutableArrayRef matcher; - - if (g_hid_manager) - return; - - g_hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - - matcher = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick); - append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad); - - IOHIDManagerSetDeviceMatchingMultiple(g_hid_manager, matcher); - CFRelease(matcher); - - IOHIDManagerRegisterDeviceMatchingCallback(g_hid_manager, hid_manager_device_attached, 0); - IOHIDManagerScheduleWithRunLoop(g_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes); - - IOHIDManagerOpen(g_hid_manager, kIOHIDOptionsTypeNone); -} - -void osx_pad_quit(void) -{ - if (g_hid_manager) - { - IOHIDManagerClose(g_hid_manager, kIOHIDOptionsTypeNone); - IOHIDManagerUnscheduleFromRunLoop(g_hid_manager, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); - - CFRelease(g_hid_manager); - } - - g_hid_manager = 0; -} diff --git a/input/apple_input.c b/input/apple_input.c index 0be77ed51d..b000bbb4a2 100644 --- a/input/apple_input.c +++ b/input/apple_input.c @@ -244,8 +244,7 @@ enum input_devices DEVICE_LAST }; -extern const rarch_joypad_driver_t apple_joypad; -static const rarch_joypad_driver_t* const g_joydriver = &apple_joypad; +static const rarch_joypad_driver_t *joypad; apple_input_data_t g_current_input_data; @@ -480,7 +479,7 @@ static bool apple_key_pressed(enum retro_key key) static bool apple_is_pressed(unsigned port_num, const struct retro_keybind *binds, unsigned key) { - return apple_key_pressed(binds[key].key) || input_joypad_pressed(g_joydriver, port_num, binds, key); + return apple_key_pressed(binds[key].key) || input_joypad_pressed(joypad, port_num, binds, key); } // Exported input driver @@ -488,6 +487,8 @@ static void *apple_input_init(void) { input_init_keyboard_lut(apple_key_map_hidusage); memset(&g_current_input_data, 0, sizeof(g_current_input_data)); + + joypad = input_joypad_init_driver(g_settings.input.joypad_driver); return (void*)-1; } @@ -507,7 +508,7 @@ static void apple_input_poll(void *data) &g_current_input_data.touches[i].full_x, &g_current_input_data.touches[i].full_y); } - input_joypad_poll(g_joydriver); + input_joypad_poll(joypad); g_current_input_data.pad_buttons[0] |= apple_input_get_icade_buttons(); g_current_input_data.mouse_delta[0] = 0; @@ -524,7 +525,7 @@ static int16_t apple_input_state(void *data, const struct retro_keybind **binds, return (id < RARCH_BIND_LIST_END) ? apple_is_pressed(port, binds[port], id) : 0; case RETRO_DEVICE_ANALOG: - return input_joypad_analog(g_joydriver, port, index, id, binds[port]); + return input_joypad_analog(joypad, port, index, id, binds[port]); case RETRO_DEVICE_KEYBOARD: return apple_key_pressed(id); @@ -586,8 +587,8 @@ static void apple_input_free_input(void *data) { (void)data; - if (g_joydriver && g_joydriver->destroy) - g_joydriver->destroy(); + if (joypad) + joypad->destroy(); } static void apple_input_set_keybinds(void *data, unsigned device, unsigned port, @@ -695,7 +696,7 @@ static void apple_input_set_keybinds(void *data, unsigned device, unsigned port, static bool apple_input_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength) { (void)data; - return input_joypad_set_rumble(g_joydriver, port, effect, strength); + return input_joypad_set_rumble(joypad, port, effect, strength); } static uint64_t apple_input_get_capabilities(void *data) @@ -720,7 +721,7 @@ static unsigned apple_devices_size(void *data) const rarch_joypad_driver_t *apple_get_joypad_driver(void *data) { - return g_joydriver; + return joypad; } const input_driver_t input_apple = { diff --git a/input/apple_joypad.c b/input/apple_joypad.c index 6a53d18d88..50a7f99a4e 100644 --- a/input/apple_joypad.c +++ b/input/apple_joypad.c @@ -13,6 +13,7 @@ * If not, see . */ +#include "apple_input.h" #include "input_common.h" #include "../general.h" @@ -21,7 +22,133 @@ #include "../apple/iOS/bluetooth/btpad.c" #include "../apple/iOS/bluetooth/btpad_queue.c" #elif defined(OSX) -#include "apple_hid_pad.c" +#include +#endif + +#ifdef OSX +struct apple_pad_connection +{ + uint32_t slot; + IOHIDDeviceRef device; + uint8_t data[2048]; +}; + +static IOHIDManagerRef g_hid_manager; + +void apple_pad_send_control(struct apple_pad_connection* connection, uint8_t* data, size_t size) +{ + IOHIDDeviceSetReport(connection->device, kIOHIDReportTypeOutput, 0x01, data + 1, size - 1); +} + +// NOTE: I pieced this together through trial and error, any corrections are welcome +static void hid_device_input_callback(void* context, IOReturn result, void* sender, IOHIDValueRef value) +{ + IOHIDElementRef element; + uint32_t type, page, use; + struct apple_pad_connection* connection = (struct apple_pad_connection*)context; + + element = IOHIDValueGetElement(value); + type = IOHIDElementGetType(element); + page = IOHIDElementGetUsagePage(element); + use = IOHIDElementGetUsage(element); + + // Joystick handler: TODO: Can GamePad work the same? + if (type == kIOHIDElementTypeInput_Button && page == kHIDPage_Button) + { + CFIndex state = IOHIDValueGetIntegerValue(value); + + if (state) + g_current_input_data.pad_buttons[connection->slot] |= (1 << (use - 1)); + else + g_current_input_data.pad_buttons[connection->slot] &= ~(1 << (use - 1)); + } + else if (type == kIOHIDElementTypeInput_Misc && page == kHIDPage_GenericDesktop) + { + static const uint32_t axis_use_ids[4] = { 48, 49, 50, 53 }; + int i; + + for (i = 0; i < 4; i ++) + { + if (use == axis_use_ids[i]) + { + CFIndex min, max, state; + float val; + + min = IOHIDElementGetPhysicalMin(element); + max = IOHIDElementGetPhysicalMax(element) - min; + state = IOHIDValueGetIntegerValue(value) - min; + + val = (float)state / (float)max; + g_current_input_data.pad_axis[connection->slot][i] = ((val * 2.0f) - 1.0f) * 32767.0f; + } + } + } +} + +static void hid_device_removed(void* context, IOReturn result, void* sender) +{ + struct apple_pad_connection* connection = (struct apple_pad_connection*)context; + + if (connection && connection->slot < MAX_PLAYERS) + { + g_current_input_data.pad_buttons[connection->slot] = 0; + memset(g_current_input_data.pad_axis[connection->slot], 0, sizeof(g_current_input_data.pad_axis)); + + apple_joypad_disconnect(connection->slot); + free(connection); + } + + IOHIDDeviceClose(sender, kIOHIDOptionsTypeNone); +} + +static void hid_device_report(void* context, IOReturn result, void *sender, IOHIDReportType type, uint32_t reportID, uint8_t *report, CFIndex reportLength) +{ + struct apple_pad_connection* connection = (struct apple_pad_connection*)context; + apple_joypad_packet(connection->slot, connection->data, reportLength + 1); +} + +static void hid_manager_device_attached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) +{ + char device_name[1024]; + CFStringRef device_name_ref; + struct apple_pad_connection* connection = (struct apple_pad_connection*)calloc(1, sizeof(*connection)); + + connection->device = device; + connection->slot = MAX_PLAYERS; + + IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone); + IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + IOHIDDeviceRegisterRemovalCallback(device, hid_device_removed, connection); + + device_name_ref = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); + CFStringGetCString(device_name_ref, device_name, sizeof(device_name), kCFStringEncodingUTF8); + + connection->slot = apple_joypad_connect(device_name, connection); + + if (apple_joypad_has_interface(connection->slot)) + IOHIDDeviceRegisterInputReportCallback(device, connection->data + 1, sizeof(connection->data) - 1, hid_device_report, connection); + else + IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection); +} + +static void append_matching_dictionary(CFMutableArrayRef array, uint32_t page, uint32_t use) +{ + CFNumberRef pagen, usen; + CFMutableDictionaryRef matcher; + + matcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + pagen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); + CFDictionarySetValue(matcher, CFSTR(kIOHIDDeviceUsagePageKey), pagen); + CFRelease(pagen); + + usen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &use); + CFDictionarySetValue(matcher, CFSTR(kIOHIDDeviceUsageKey), usen); + CFRelease(usen); + + CFArrayAppendValue(array, matcher); + CFRelease(matcher); +} #endif #include "../apple/common/hidpad/wiimote.c" @@ -137,6 +264,26 @@ bool apple_joypad_has_interface(uint32_t slot) // RetroArch joypad driver: static bool apple_joypad_init(void) { +#ifdef OSX + CFMutableArrayRef matcher; + + if (!g_hid_manager) + { + g_hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + + matcher = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick); + append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad); + + IOHIDManagerSetDeviceMatchingMultiple(g_hid_manager, matcher); + CFRelease(matcher); + + IOHIDManagerRegisterDeviceMatchingCallback(g_hid_manager, hid_manager_device_attached, 0); + IOHIDManagerScheduleWithRunLoop(g_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes); + + IOHIDManagerOpen(g_hid_manager, kIOHIDOptionsTypeNone); + } +#endif return true; } @@ -157,6 +304,17 @@ static void apple_joypad_destroy(void) slots[i].iface->set_rumble(slots[i].data, RETRO_RUMBLE_WEAK, 0); } } + +#ifdef OSX + if (g_hid_manager) + { + IOHIDManagerClose(g_hid_manager, kIOHIDOptionsTypeNone); + IOHIDManagerUnscheduleFromRunLoop(g_hid_manager, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + + CFRelease(g_hid_manager); + } + g_hid_manager = NULL; +#endif } static bool apple_joypad_button(unsigned port, uint16_t joykey) diff --git a/input/input_common.c b/input/input_common.c index d1779cf2c9..137421f659 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -74,6 +74,9 @@ static const rarch_joypad_driver_t *joypad_drivers[] = { #ifdef HAVE_SDL &sdl_joypad, #endif +#ifdef __MACH__ + &apple_joypad, +#endif #endif NULL, }; diff --git a/input/input_common.h b/input/input_common.h index efc6b14aef..f8f5a1ed2d 100644 --- a/input/input_common.h +++ b/input/input_common.h @@ -109,6 +109,7 @@ extern const rarch_joypad_driver_t ps3_joypad; extern const rarch_joypad_driver_t psp_joypad; extern const rarch_joypad_driver_t xdk_joypad; extern const rarch_joypad_driver_t gx_joypad; +extern const rarch_joypad_driver_t apple_joypad; struct rarch_key_map {