33- (void) handleInputEvent:(IOHIDValueRef)value;
34- (void) handleJoystickAttach:(IOHIDDeviceRef)device;
35- (void) handleDeviceRemoval:(IOHIDDeviceRef)device;
41static void HandleInputValueCallback(
void * inContext, IOReturn inResult,
void* inSender, IOHIDValueRef inIOHIDValueRef);
49 if ((
self = [super
init]))
55 double x = ((double) i - 128.0) / 128.0;
56 double sign =
x>=0 ? 1.0 : -1.0;
57 double y = sign * floor(32767.0 * pow (fabs(
x),
STICK_GAMMA));
70 hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
71 IOHIDManagerSetDeviceMatching(
hidManager, NULL);
76 IOHIDManagerScheduleWithRunLoop(
hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
77 IOReturn iores = IOHIDManagerOpen(
hidManager, kIOHIDOptionsTypeNone);
78 if (iores != kIOReturnSuccess)
80 OOLog(
@"joystick.error.init",
@"Cannot open HID manager; joystick support will not function.");
83 devices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
100 return CFArrayGetCount(
devices);
104- (void) handleDeviceAttach:(IOHIDDeviceRef)device
106 NSArray *usagePairs = (NSArray *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDDeviceUsagePairsKey));
108 for (NSDictionary *pair in usagePairs)
110 if ([pair oo_unsignedIntForKey:@kIOHIDDeviceUsagePageKey] == kHIDPage_GenericDesktop)
112 unsigned usage = [pair oo_unsignedIntForKey:@kIOHIDDeviceUsageKey];
113 if (usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad)
115 [
self handleJoystickAttach:device];
123 NSString *product = (NSString *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
124 unsigned usagePage = [(NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey)) unsignedIntValue];
125 unsigned usage = [(NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey)) unsignedIntValue];
126 OOLog(
@"joystick.reject",
@"Ignoring HID device: %@ (primary usage %u:%u)", product, usagePage, usage);
131- (void) handleJoystickAttach:(IOHIDDeviceRef)device
133 OOLog(
@"joystick.connect",
@"Joystick connected: %@", IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)));
135 CFArrayAppendValue(
devices, device);
141 CFArrayRef elementList = IOHIDDeviceCopyMatchingElements(device, NULL, 0L);
142 if (elementList != NULL)
146 CFIndex idx,
count = CFArrayGetCount(elementList);
148 for (idx = 0; idx <
count; idx++)
150 IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elementList, idx);
151 IOHIDElementType elementType = IOHIDElementGetType(element);
152 if (elementType > kIOHIDElementTypeInput_ScanCodes)
156 IOHIDElementCookie elementCookie = IOHIDElementGetCookie(element);
157 uint32_t usagePage = IOHIDElementGetUsagePage(element);
158 uint32_t usage = IOHIDElementGetUsage(element);
159 uint32_t min = (uint32_t)IOHIDElementGetPhysicalMin(element);
160 uint32_t max = (uint32_t)IOHIDElementGetPhysicalMax(element);
161 NSString *name = (NSString *)IOHIDElementGetProperty(element, CFSTR(kIOHIDElementNameKey)) ?:
@"unnamed";
162 OOLog(
@"joystick.connect.element",
@"%@ - usage %d:%d, cookie %d, range %d-%d", name, usagePage, usage, (
int) elementCookie, min, max);
166 CFRelease(elementList);
172- (void) handleDeviceRemoval:(IOHIDDeviceRef)device
174 OOLog(
@"joystick.remove",
@"Joystick removed: %@", IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)));
176 CFIndex index = CFArrayGetFirstIndexOfValue(
devices, CFRangeMake(0, CFArrayGetCount(
devices)), device);
177 if (index != kCFNotFound) CFArrayRemoveValueAtIndex(
devices, index);
200 case kHIDPage_GenericDesktop:
203 case kHIDUsage_GD_X:
return 0;
204 case kHIDUsage_GD_Y:
return 1;
205 case kHIDUsage_GD_Z:
return 2;
206 case kHIDUsage_GD_Rx:
return 3;
207 case kHIDUsage_GD_Ry:
return 4;
208 case kHIDUsage_GD_Rz:
return 5;
209 case kHIDUsage_GD_Slider:
return 6;
210 case kHIDUsage_GD_Dial:
return 7;
211 case kHIDUsage_GD_Wheel:
return 8;
215 case kHIDPage_Simulation:
218 case kHIDUsage_Sim_Throttle:
236 if (0 <= value && value <= max)
241 return valueMap4[value];
246 return valueMap8[value];
253- (void) handleInputEvent:(IOHIDValueRef)value
255 IOHIDElementRef element = IOHIDValueGetElement(value);
256 uint32_t usagePage = IOHIDElementGetUsagePage(element);
257 uint32_t usage = IOHIDElementGetUsage(element);
269 CFIndex intValue = IOHIDValueGetIntegerValue(value);
270 CFIndex min = IOHIDElementGetLogicalMin(element);
271 CFIndex max = IOHIDElementGetLogicalMax(element);
272 float axisValue = (float)(intValue - min) / (float)(max + 1 - min);
288 OOLogERR(
@"joystick.gamma.overflow",
@"Joystick gamma table overflow - gammaIndex is %u of %u. Raw value: %i in [%i..%i]; axisValue: %g; unrounded gammaIndex: %g. Ignoring event. This is an internal error, please report it.",
290 (
int)intValue, (
int)min, (
int)max,
300 [
self decodeAxisEvent:&evt];
302 else if (usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Hatswitch)
304 CFIndex max = IOHIDElementGetLogicalMax(element);
305 CFIndex min = IOHIDElementGetLogicalMin(element);
312 .value =
MapHatValue(IOHIDValueGetIntegerValue(value) - min, max - min)
315 [
self decodeHatEvent:&evt];
317 else if (usagePage == kHIDPage_Button)
322 BOOL buttonState = (IOHIDValueGetIntegerValue(value) != 0);
326 evt.
state = buttonState ? 1 : 0;
327 [
self decodeButtonEvent:&evt];
332- (NSString *) nameOfJoystick:(NSUInteger)stickNumber
334 IOHIDDeviceRef device = (IOHIDDeviceRef)CFArrayGetValueAtIndex(
devices, stickNumber);
335 return (NSString *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
340- (int16_t) getAxisWithStick:(NSUInteger) stickNum axis:(NSUInteger) axisNum
#define OOLogERR(class, format,...)
BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass)
#define OOLog(class, format,...)
@ kJoystickGammaTableSize
static void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef)
static void HandleInputValueCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDValueRef inIOHIDValueRef)
static void HandleDeviceMatchingCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef)
NSUInteger joystickCount()
static int AxisIndex(uint32_t page, uint32_t usage)
IOHIDManagerRef hidManager
CFMutableArrayRef devices
static uint8_t MapHatValue(CFIndex value, CFIndex max)
int gammaTable[kJoystickGammaTableSize]
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque