Skip to content

Commit

Permalink
update to use silicon
Browse files Browse the repository at this point in the history
  • Loading branch information
ColleagueRiley committed Dec 27, 2024
1 parent 59c1262 commit f97b2cf
Showing 1 changed file with 113 additions and 61 deletions.
174 changes: 113 additions & 61 deletions examples/general/gamepad.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,91 +2,143 @@
#define SILICON_IMPLEMENTATION
#include <silicon.h>

#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDManager.h>
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>

NSApplication* NSApp;

void Handle_DeviceMatchingCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device);
void Handle_DeviceRemovalCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device);
void Handle_InputValueCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value);

typedef struct {
IOHIDManagerRef hidManager;
} AppDelegate;

void applicationDidFinishLaunching(AppDelegate *appDelegate) {
appDelegate->hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);

CFDictionaryRef criteria = CFDictionaryCreate(kCFAllocatorDefault,
(const void *[]){ CFSTR(kIOHIDDeviceUsagePageKey), CFSTR(kIOHIDDeviceUsageKey) },
(const void *[]){ CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(int){kHIDPage_GenericDesktop}),
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(int){kHIDUsage_GD_GamePad}) },
2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

IOHIDManagerSetDeviceMatching(appDelegate->hidManager, criteria);
CFRelease(criteria);

IOHIDManagerRegisterDeviceMatchingCallback(appDelegate->hidManager, Handle_DeviceMatchingCallback, appDelegate);
IOHIDManagerRegisterDeviceRemovalCallback(appDelegate->hidManager, Handle_DeviceRemovalCallback, appDelegate);
IOHIDManagerRegisterInputValueCallback(appDelegate->hidManager, Handle_InputValueCallback, appDelegate);

IOHIDManagerScheduleWithRunLoop(appDelegate->hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerOpen(appDelegate->hidManager, kIOHIDOptionsTypeNone);
}

void applicationWillTerminate(AppDelegate *appDelegate) {
IOHIDManagerClose(appDelegate->hidManager, kIOHIDOptionsTypeNone);
CFRelease(appDelegate->hidManager);
}
NSApplication* NSApp;

void Handle_DeviceMatchingCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {
printf("Gamepad connected: %p\n", device);
}

void Handle_DeviceRemovalCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {
printf("Gamepad disconnected: %p\n", device);
}

void Handle_InputValueCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
// Callback for device input value changes
void inputValueChangedCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) {
IOHIDElementRef element = IOHIDValueGetElement(value);

// Get the usage page and usage
uint32_t usagePage = IOHIDElementGetUsagePage(element);
uint32_t usage = IOHIDElementGetUsage(element);
CFIndex logicalValue = IOHIDValueGetIntegerValue(value);


// Get the integer value of the input
CFIndex intValue = IOHIDValueGetIntegerValue(value);

// Handle buttons
if (usagePage == kHIDPage_Button) {
printf("Button %d: %ld\n", usage, logicalValue);
} else if (usagePage == kHIDPage_GenericDesktop) {
printf("Button %u: %s\n", usage, intValue ? "Pressed" : "Released");
}

// Handle joystick movements (axes)
if (usagePage == kHIDPage_GenericDesktop) {
switch (usage) {
case kHIDUsage_GD_X:
printf("X Axis: %ld\n", logicalValue);
printf("Joystick X-axis: %ld\n", intValue);
break;
case kHIDUsage_GD_Y:
printf("Y Axis: %ld\n", logicalValue);
printf("Joystick Y-axis: %ld\n", intValue);
break;
case kHIDUsage_GD_Z:
printf("Z Axis: %ld\n", logicalValue);
printf("Joystick Z-axis: %ld\n", intValue);
break;
case kHIDUsage_GD_Rx:
printf("Rx Axis: %ld\n", logicalValue);
printf("Joystick Rx-axis: %ld\n", intValue);
break;
case kHIDUsage_GD_Ry:
printf("Ry Axis: %ld\n", logicalValue);
break;
case kHIDUsage_GD_Rz:
printf("Rz Axis: %ld\n", logicalValue);
printf("Joystick Ry-axis: %ld\n", intValue);
break;
default:
break;
}
}
}

int main(int argc, const char * argv[]) {
AppDelegate appDelegate;
applicationDidFinishLaunching(&appDelegate);
NSApp = NSApplication_sharedApplication();

NSApplication_run(NSApp);
applicationWillTerminate(&appDelegate);
// Callback for when an HID device is added
void deviceAddedCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {
CFStringRef deviceName = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
if (deviceName) {
char buffer[128];
if (CFStringGetCString(deviceName, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {
printf("Device added: %s\n", buffer);
}
}

// Register input value callback for the device
IOHIDDeviceRegisterInputValueCallback(device, inputValueChangedCallback, NULL);
}

// Callback for when an HID device is removed
void deviceRemovedCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef device) {
printf("Device removed.\n");
}

int main(int argc, char* argv[]) {
NSApp = NSApplication_sharedApplication();

NSWindow* window1 = NSWindow_init(NSMakeRect(100, 100, 300, 300), NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false);
NSWindow_setIsVisible(window1, true);

NSApplication_setActivationPolicy(NSApp, NSApplicationActivationPolicyRegular);
NSApplication_finishLaunching(NSApp);

// Create an IOHIDManager
IOHIDManagerRef hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
if (!hidManager) {
fprintf(stderr, "Failed to create IOHIDManager.\n");
return -1;
}

// Define the matching criteria for devices
CFMutableDictionaryRef matchingDictionary = CFDictionaryCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
);
if (!matchingDictionary) {
fprintf(stderr, "Failed to create matching dictionary.\n");
CFRelease(hidManager);
return -1;
}

// Specify usage page and usage for generic desktop controls (joysticks, gamepads, etc.)
CFDictionarySetValue(
matchingDictionary,
CFSTR(kIOHIDDeviceUsagePageKey),
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(int){kHIDPage_GenericDesktop})
);

// Set the matching criteria to the HID manager
IOHIDManagerSetDeviceMatching(hidManager, matchingDictionary);

// Register callbacks for device detection
IOHIDManagerRegisterDeviceMatchingCallback(hidManager, deviceAddedCallback, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(hidManager, deviceRemovedCallback, NULL);

// Schedule the HID manager with the run loop
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);

// Open the HID manager
IOReturn result = IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);
if (result != kIOReturnSuccess) {
fprintf(stderr, "Failed to open IOHIDManager.\n");
CFRelease(matchingDictionary);
CFRelease(hidManager);
return -1;
}

printf("Listening for HID devices and input. Press Ctrl+C to exit.\n");

// Run the main loop
while (true) {
NSEvent* event = NSApplication_nextEventMatchingMask(NSApp, NSEventMaskAny, NSDate_distantFuture(), NSDefaultRunLoopMode, true);

CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, false); // Poll the run loop with a timeout
NSApplication_sendEvent(NSApp, event);
NSApplication_updateWindows(NSApp);
}

// Clean up
CFRelease(matchingDictionary);
IOHIDManagerClose(hidManager, kIOHIDOptionsTypeNone);
CFRelease(hidManager);

return 0;
}

0 comments on commit f97b2cf

Please sign in to comment.