| 
									
										
										
										
											2014-02-10 13:54:46 -05:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project | 
					
						
							|  |  |  | // Licensed under GPLv2 | 
					
						
							|  |  |  | // Refer to the license.txt file included. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | #include <Foundation/Foundation.h> | 
					
						
							|  |  |  | #include <IOKit/hid/IOHIDLib.h> | 
					
						
							| 
									
										
										
										
											2013-01-17 23:32:07 -08:00
										 |  |  | #include <Cocoa/Cocoa.h> | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "InputCommon/ControllerInterface/OSX/OSX.h" | 
					
						
							|  |  |  | #include "InputCommon/ControllerInterface/OSX/OSXKeyboard.h" | 
					
						
							|  |  |  | #include "InputCommon/ControllerInterface/OSX/OSXJoystick.h" | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-16 20:07:10 -04:00
										 |  |  | #include <map> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | namespace ciface | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | namespace OSX | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | static IOHIDManagerRef HIDManager = nullptr; | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | static CFStringRef OurRunLoop = CFSTR("DolphinOSXInput"); | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | static std::map<std::string, int> kbd_name_counts, joy_name_counts; | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | void DeviceElementDebugPrint(const void *value, void *context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	IOHIDElementRef e = (IOHIDElementRef)value; | 
					
						
							|  |  |  | 	bool recurse = false; | 
					
						
							|  |  |  | 	if (context) | 
					
						
							|  |  |  | 		recurse = *(bool*)context; | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	std::string type = ""; | 
					
						
							| 
									
										
										
										
											2014-08-30 16:44:28 -04:00
										 |  |  | 	switch (IOHIDElementGetType(e)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	case kIOHIDElementTypeInput_Axis: | 
					
						
							|  |  |  | 		type = "axis"; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case kIOHIDElementTypeInput_Button: | 
					
						
							|  |  |  | 		type = "button"; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case kIOHIDElementTypeInput_Misc: | 
					
						
							|  |  |  | 		type = "misc"; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case kIOHIDElementTypeInput_ScanCodes: | 
					
						
							|  |  |  | 		type = "scancodes"; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case kIOHIDElementTypeOutput: | 
					
						
							|  |  |  | 		type = "output"; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case kIOHIDElementTypeFeature: | 
					
						
							|  |  |  | 		type = "feature"; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case kIOHIDElementTypeCollection: | 
					
						
							|  |  |  | 		type = "collection"; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	std::string c_type = ""; | 
					
						
							|  |  |  | 	if (type == "collection") | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-08-30 16:44:28 -04:00
										 |  |  | 		switch (IOHIDElementGetCollectionType(e)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 		case kIOHIDElementCollectionTypePhysical: | 
					
						
							|  |  |  | 			c_type = "physical"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case kIOHIDElementCollectionTypeApplication: | 
					
						
							|  |  |  | 			c_type = "application"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case kIOHIDElementCollectionTypeLogical: | 
					
						
							|  |  |  | 			c_type = "logical"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case kIOHIDElementCollectionTypeReport: | 
					
						
							|  |  |  | 			c_type = "report"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case kIOHIDElementCollectionTypeNamedArray: | 
					
						
							|  |  |  | 			c_type = "namedArray"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case kIOHIDElementCollectionTypeUsageSwitch: | 
					
						
							|  |  |  | 			c_type = "usageSwitch"; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case kIOHIDElementCollectionTypeUsageModifier: | 
					
						
							|  |  |  | 			c_type = "usageModifier"; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	c_type.append(" "); | 
					
						
							| 
									
										
										
										
											2011-01-27 05:01:00 +00:00
										 |  |  | 	NSLog(@"%s%s%spage: 0x%x usage: 0x%x name: %@ " | 
					
						
							|  |  |  | 		"lmin: %ld lmax: %ld pmin: %ld pmax: %ld", | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 		  type.c_str(), | 
					
						
							|  |  |  | 		  type == "collection" ? ":" : "", | 
					
						
							|  |  |  | 		  type == "collection" ? c_type.c_str() : " ", | 
					
						
							|  |  |  | 		  IOHIDElementGetUsagePage(e), | 
					
						
							|  |  |  | 		  IOHIDElementGetUsage(e), | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 		  IOHIDElementGetName(e),		// usually just nullptr | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 		  IOHIDElementGetLogicalMin(e), | 
					
						
							|  |  |  | 		  IOHIDElementGetLogicalMax(e), | 
					
						
							|  |  |  | 		  IOHIDElementGetPhysicalMin(e), | 
					
						
							|  |  |  | 		  IOHIDElementGetPhysicalMax(e)); | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	if ((type == "collection") && recurse) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		CFArrayRef elements = IOHIDElementGetChildren(e); | 
					
						
							|  |  |  | 		CFRange range = {0, CFArrayGetCount(elements)}; | 
					
						
							|  |  |  | 		// this leaks...but it's just debug code, right? :D | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 		CFArrayApplyFunction(elements, range, | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 			DeviceElementDebugPrint, nullptr); | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DeviceDebugPrint(IOHIDDeviceRef device) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | #if 0 | 
					
						
							|  |  |  | #define shortlog(x) NSLog(@"%s: %@", \ | 
					
						
							|  |  |  | 		x, IOHIDDeviceGetProperty(device, CFSTR(x))); | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	NSLog(@"-------------------------"); | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	NSLog(@"Got Device: %@", | 
					
						
							|  |  |  | 		IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))); | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	shortlog(kIOHIDTransportKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDVendorIDKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDVendorIDSourceKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDProductIDKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDVersionNumberKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDManufacturerKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDProductKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDSerialNumberKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDCountryCodeKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDLocationIDKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDDeviceUsageKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDDeviceUsagePageKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDDeviceUsagePairsKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDPrimaryUsageKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDPrimaryUsagePageKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDMaxInputReportSizeKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDMaxOutputReportSizeKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDMaxFeatureReportSizeKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDReportIntervalKey) | 
					
						
							|  |  |  | 	shortlog(kIOHIDReportDescriptorKey) | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-17 23:32:07 -08:00
										 |  |  | static void *g_window; | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | static void DeviceMatching_callback(void* inContext, | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	IOReturn inResult, | 
					
						
							|  |  |  | 	void *inSender, | 
					
						
							|  |  |  | 	IOHIDDeviceRef inIOHIDDeviceRef) | 
					
						
							| 
									
										
										
										
											2010-04-25 23:41:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-15 12:50:47 +00:00
										 |  |  | 	NSString *pName = (NSString *) | 
					
						
							|  |  |  | 		IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductKey)); | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 	std::string name = (pName != nullptr) ? [pName UTF8String] : "Unknown device"; | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-27 15:22:23 +00:00
										 |  |  | 	DeviceDebugPrint(inIOHIDDeviceRef); | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-16 20:07:10 -04:00
										 |  |  | 	std::vector<Core::Device*> *devices = | 
					
						
							|  |  |  | 		(std::vector<Core::Device*> *)inContext; | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 	// Add to the devices vector if it's of a type we want | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, | 
					
						
							| 
									
										
										
										
											2011-01-14 05:06:08 +00:00
										 |  |  | 		kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard)) | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | 		devices->push_back(new Keyboard(inIOHIDDeviceRef, | 
					
						
							| 
									
										
										
										
											2013-01-17 23:32:07 -08:00
										 |  |  | 			name, kbd_name_counts[name]++, g_window)); | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | #if 0 | 
					
						
							| 
									
										
										
										
											2011-01-14 05:06:08 +00:00
										 |  |  | 	else if (IOHIDDeviceConformsTo(inIOHIDDeviceRef, | 
					
						
							|  |  |  | 		kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse)) | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | 		devices->push_back(new Mouse(inIOHIDDeviceRef, | 
					
						
							| 
									
										
										
										
											2011-06-15 12:50:47 +00:00
										 |  |  | 			name, mouse_name_counts[name]++)); | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2011-01-14 05:06:08 +00:00
										 |  |  | 	else  | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | 		devices->push_back(new Joystick(inIOHIDDeviceRef, | 
					
						
							|  |  |  | 			name, joy_name_counts[name]++)); | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-16 20:07:10 -04:00
										 |  |  | void Init(std::vector<Core::Device*>& devices, void *window) | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, | 
					
						
							|  |  |  | 		kIOHIDOptionsTypeNone); | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 	if (!HIDManager) | 
					
						
							|  |  |  | 		NSLog(@"Failed to create HID Manager reference"); | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-17 23:32:07 -08:00
										 |  |  | 	g_window = window; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 	IOHIDManagerSetDeviceMatching(HIDManager, nullptr); | 
					
						
							| 
									
										
										
										
											2010-04-25 23:41:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	// Callbacks for acquisition or loss of a matching device | 
					
						
							|  |  |  | 	IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, | 
					
						
							|  |  |  | 		DeviceMatching_callback, (void *)&devices); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Match devices that are plugged in right now | 
					
						
							|  |  |  | 	IOHIDManagerScheduleWithRunLoop(HIDManager, | 
					
						
							|  |  |  | 		CFRunLoopGetCurrent(), OurRunLoop); | 
					
						
							|  |  |  | 	if (IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone) != | 
					
						
							|  |  |  | 		kIOReturnSuccess) | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 		NSLog(@"Failed to open HID Manager"); | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-30 05:46:19 +00:00
										 |  |  | 	kbd_name_counts.clear(); | 
					
						
							|  |  |  | 	joy_name_counts.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | 	// Wait while current devices are initialized | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	while (CFRunLoopRunInMode(OurRunLoop, 0, TRUE) == | 
					
						
							| 
									
										
										
										
											2010-11-13 20:02:01 +00:00
										 |  |  | 		kCFRunLoopRunHandledSource) {}; | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Things should be configured now | 
					
						
							|  |  |  | 	// Disable hotplugging and other scheduling | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 	IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, nullptr, nullptr); | 
					
						
							| 
									
										
										
										
											2010-06-26 13:03:25 +00:00
										 |  |  | 	IOHIDManagerUnscheduleFromRunLoop(HIDManager, | 
					
						
							|  |  |  | 		CFRunLoopGetCurrent(), OurRunLoop); | 
					
						
							| 
									
										
										
										
											2010-04-25 18:04:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DeInit() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// This closes all devices as well | 
					
						
							|  |  |  | 	IOHIDManagerClose(HIDManager, kIOHIDOptionsTypeNone); | 
					
						
							|  |  |  | 	CFRelease(HIDManager); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } |