From 4a569be6f6f3107d5e85e6eb5e5d90e9fbf7e8eb Mon Sep 17 00:00:00 2001 From: TotallyGamerJet Date: Thu, 15 Sep 2022 11:11:59 -0400 Subject: [PATCH] internal/gamepad: remove Cgo on darwin (#2330) Updates #1162 --- go.mod | 2 +- go.sum | 4 +- internal/gamepad/api_cf_darwin.go | 138 +++++++++++++++++++++ internal/gamepad/api_hid_darwin.go | 185 +++++++++++++++++++++++++++ internal/gamepad/gamepad_darwin.go | 193 ++++++++++++----------------- 5 files changed, 405 insertions(+), 117 deletions(-) create mode 100644 internal/gamepad/api_cf_darwin.go create mode 100644 internal/gamepad/api_hid_darwin.go diff --git a/go.mod b/go.mod index cd789ef56..420ed1274 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/hajimehoshi/ebiten/v2 go 1.16 require ( - github.com/ebitengine/purego v0.0.0-20220910041003-a51c01493ff9 + github.com/ebitengine/purego v0.2.0-alpha.0.20220915044048-aa1b0f680473 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad github.com/hajimehoshi/bitmapfont/v2 v2.2.1 github.com/hajimehoshi/go-mp3 v0.3.3 diff --git a/go.sum b/go.sum index ee557a029..7b67a1742 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ebitengine/purego v0.0.0-20220907032450-cf3e27c364c7/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg= -github.com/ebitengine/purego v0.0.0-20220910041003-a51c01493ff9 h1:SWRYqW9r4JvlnVnDurFzaF+0X60GG5QZD8n0U9cq3Gw= -github.com/ebitengine/purego v0.0.0-20220910041003-a51c01493ff9/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg= +github.com/ebitengine/purego v0.2.0-alpha.0.20220915044048-aa1b0f680473 h1:gvI3mxzjexvkakZNJkYRZOIWRQTGa8ucsQtQ/tN2VJk= +github.com/ebitengine/purego v0.2.0-alpha.0.20220915044048-aa1b0f680473/go.mod h1:8K86Hsai2ghNjg9h/9P9tDdLAhUNwqNg10OESLDOam8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k= diff --git a/internal/gamepad/api_cf_darwin.go b/internal/gamepad/api_cf_darwin.go new file mode 100644 index 000000000..1dcca8ef8 --- /dev/null +++ b/internal/gamepad/api_cf_darwin.go @@ -0,0 +1,138 @@ +// Copyright 2022 The Ebitengine Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gamepad + +import ( + "unsafe" + + "github.com/ebitengine/purego" +) + +type _CFIndex int64 +type _CFAllocatorRef uintptr +type _CFArrayRef uintptr +type _CFDictionaryRef uintptr +type _CFNumberRef uintptr +type _CFTypeRef uintptr +type _CFRunLoopRef uintptr +type _CFNumberType uintptr +type _CFStringRef uintptr +type _CFArrayCallBacks struct{} +type _CFDictionaryKeyCallBacks struct{} +type _CFDictionaryValueCallBacks struct{} +type _CFRunLoopRunResult int32 +type _CFRunLoopMode = _CFStringRef +type _CFTimeInterval float64 +type _CFTypeID uint64 +type _CFStringEncoding uint32 + +var kCFAllocatorDefault _CFAllocatorRef = 0 + +const ( + kCFStringEncodingUTF8 _CFStringEncoding = 0x08000100 +) + +const ( + kCFNumberSInt32Type _CFNumberType = 3 + kCFNumberIntType _CFNumberType = 9 +) + +var ( + corefoundation = purego.Dlopen("CoreFoundation.framework/CoreFoundation", purego.RTLD_GLOBAL) + procCFNumberCreate = purego.Dlsym(corefoundation, "CFNumberCreate") + procCFNumberGetValue = purego.Dlsym(corefoundation, "CFNumberGetValue") + procCFArrayCreate = purego.Dlsym(corefoundation, "CFArrayCreate") + procCFArrayGetCount = purego.Dlsym(corefoundation, "CFArrayGetCount") + procCFArrayGetValueAtIndex = purego.Dlsym(corefoundation, "CFArrayGetValueAtIndex") + procCFDictionaryCreate = purego.Dlsym(corefoundation, "CFDictionaryCreate") + procCFRelease = purego.Dlsym(corefoundation, "CFRelease") + procCFRunLoopGetMain = purego.Dlsym(corefoundation, "CFRunLoopGetMain") + procCFRunLoopRunInMode = purego.Dlsym(corefoundation, "CFRunLoopRunInMode") + procCFGetTypeID = purego.Dlsym(corefoundation, "CFGetTypeID") + procCFStringGetCString = purego.Dlsym(corefoundation, "CFStringGetCString") + procCFStringCreateWithCString = purego.Dlsym(corefoundation, "CFStringCreateWithCString") + + kCFTypeDictionaryKeyCallBacks = purego.Dlsym(corefoundation, "kCFTypeDictionaryKeyCallBacks") + kCFTypeDictionaryValueCallBacks = purego.Dlsym(corefoundation, "kCFTypeDictionaryValueCallBacks") + kCFTypeArrayCallBacks = purego.Dlsym(corefoundation, "kCFTypeArrayCallBacks") + kCFRunLoopDefaultMode = purego.Dlsym(corefoundation, "kCFRunLoopDefaultMode") +) + +func _CFNumberCreate(allocator _CFAllocatorRef, theType _CFNumberType, valuePtr unsafe.Pointer) _CFNumberRef { + number, _, _ := purego.SyscallN(procCFNumberCreate, uintptr(allocator), uintptr(theType), uintptr(valuePtr)) + return _CFNumberRef(number) +} + +func _CFNumberGetValue(number _CFNumberRef, theType _CFNumberType, valuePtr unsafe.Pointer) bool { + ret, _, _ := purego.SyscallN(procCFNumberGetValue, uintptr(number), uintptr(theType), uintptr(valuePtr)) + return ret != 0 +} + +func _CFArrayCreate(allocator _CFAllocatorRef, values *unsafe.Pointer, numValues _CFIndex, callbacks *_CFArrayCallBacks) _CFArrayRef { + ret, _, _ := purego.SyscallN(procCFArrayCreate, uintptr(allocator), uintptr(unsafe.Pointer(values)), uintptr(numValues), uintptr(unsafe.Pointer(callbacks))) + return _CFArrayRef(ret) +} + +func _CFArrayGetValueAtIndex(array _CFArrayRef, index _CFIndex) uintptr { + ret, _, _ := purego.SyscallN(procCFArrayGetValueAtIndex, uintptr(array), uintptr(index)) + return ret +} + +func _CFArrayGetCount(array _CFArrayRef) _CFIndex { + ret, _, _ := purego.SyscallN(procCFArrayGetCount, uintptr(array)) + return _CFIndex(ret) +} + +func _CFDictionaryCreate(allocator _CFAllocatorRef, keys *unsafe.Pointer, values *unsafe.Pointer, numValues _CFIndex, keyCallBacks *_CFDictionaryKeyCallBacks, valueCallBacks *_CFDictionaryValueCallBacks) _CFDictionaryRef { + ret, _, _ := purego.SyscallN(procCFDictionaryCreate, uintptr(allocator), uintptr(unsafe.Pointer(keys)), uintptr(unsafe.Pointer(values)), uintptr(numValues), uintptr(unsafe.Pointer(keyCallBacks)), uintptr(unsafe.Pointer(valueCallBacks))) + return _CFDictionaryRef(ret) +} + +func _CFRelease(cf _CFTypeRef) { + purego.SyscallN(procCFRelease, uintptr(cf)) +} + +func _CFRunLoopGetMain() _CFRunLoopRef { + ret, _, _ := purego.SyscallN(procCFRunLoopGetMain) + return _CFRunLoopRef(ret) +} + +func _CFRunLoopRunInMode(mode _CFRunLoopMode, seconds _CFTimeInterval, returnAfterSourceHandled bool) _CFRunLoopRunResult { + var b uintptr = 0 + if returnAfterSourceHandled { + b = 1 + } + if seconds != 0 { + panic("corefoundation: seconds greater than 0 is not supported") + } + //TODO: support floats + ret, _, _ := purego.SyscallN(procCFRunLoopRunInMode, uintptr(mode), b) + return _CFRunLoopRunResult(ret) +} + +func _CFGetTypeID(cf _CFTypeRef) _CFTypeID { + ret, _, _ := purego.SyscallN(procCFGetTypeID, uintptr(cf)) + return _CFTypeID(ret) +} + +func _CFStringGetCString(theString _CFStringRef, buffer []byte, encoding _CFStringEncoding) bool { + ret, _, _ := purego.SyscallN(procCFStringGetCString, uintptr(theString), uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(encoding)) + return ret != 0 +} + +func _CFStringCreateWithCString(alloc _CFAllocatorRef, cstr []byte, encoding _CFStringEncoding) _CFStringRef { + ret, _, _ := purego.SyscallN(procCFStringCreateWithCString, uintptr(alloc), uintptr(unsafe.Pointer(&cstr[0])), uintptr(encoding)) + return _CFStringRef(ret) +} diff --git a/internal/gamepad/api_hid_darwin.go b/internal/gamepad/api_hid_darwin.go new file mode 100644 index 000000000..27fd634aa --- /dev/null +++ b/internal/gamepad/api_hid_darwin.go @@ -0,0 +1,185 @@ +// Copyright 2022 The Ebitengine Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gamepad + +import ( + "unsafe" + + "github.com/ebitengine/purego" +) + +const kIOReturnSuccess = 0 + +const kIOHIDOptionsTypeNone _IOOptionBits = 0 + +const ( + kIOHIDElementTypeInput_Misc = 1 + kIOHIDElementTypeInput_Button = 2 + kIOHIDElementTypeInput_Axis = 3 +) + +const ( + kHIDPage_GenericDesktop = 0x1 + kHIDPage_Simulation = 0x2 + kHIDPage_Button = 0x9 + kHIDPage_Consumer = 0x0C +) + +const ( + kHIDUsage_GD_Joystick = 0x4 + kHIDUsage_GD_GamePad = 0x5 + kHIDUsage_GD_MultiAxisController = 0x8 + kHIDUsage_GD_X = 0x30 + kHIDUsage_GD_Y = 0x31 + kHIDUsage_GD_Z = 0x32 + kHIDUsage_GD_Rx = 0x33 + kHIDUsage_GD_Ry = 0x34 + kHIDUsage_GD_Rz = 0x35 + kHIDUsage_GD_Slider = 0x36 + kHIDUsage_GD_Dial = 0x37 + kHIDUsage_GD_Wheel = 0x38 + kHIDUsage_GD_Hatswitch = 0x39 + kHIDUsage_GD_Start = 0x3D + kHIDUsage_GD_Select = 0x3E + kHIDUsage_GD_SystemMainMenu = 0x85 + kHIDUsage_GD_DPadUp = 0x90 + kHIDUsage_GD_DPadDown = 0x91 + kHIDUsage_GD_DPadRight = 0x92 + kHIDUsage_GD_DPadLeft = 0x93 + kHIDUsage_Sim_Rudder = 0xBA + kHIDUsage_Sim_Throttle = 0xBB + kHIDUsage_Sim_Accelerator = 0xC4 + kHIDUsage_Sim_Brake = 0xC5 + kHIDUsage_Sim_Steering = 0xC8 +) + +var ( + kIOHIDVendorIDKey = []byte("VendorID\x00") + kIOHIDProductIDKey = []byte("ProductID\x00") + kIOHIDVersionNumberKey = []byte("VersionNumber\x00") + kIOHIDProductKey = []byte("Product\x00") + kIOHIDDeviceUsagePageKey = []byte("DeviceUsagePage\x00") + kIOHIDDeviceUsageKey = []byte("DeviceUsage\x00") +) + +type _IOOptionBits uint32 +type _IOHIDManagerRef uintptr +type _IOHIDDeviceRef uintptr +type _IOHIDElementRef uintptr +type _IOHIDValueRef uintptr +type _IOReturn int +type _IOHIDElementType uint + +type _IOHIDDeviceCallback func(context unsafe.Pointer, result _IOReturn, sender unsafe.Pointer, device _IOHIDDeviceRef) + +var ( + iokit = purego.Dlopen("IOKit.framework/IOKit", purego.RTLD_GLOBAL) + + procIOHIDElementGetTypeID = purego.Dlsym(iokit, "IOHIDElementGetTypeID") + procIOHIDManagerCreate = purego.Dlsym(iokit, "IOHIDManagerCreate") + procIOHIDDeviceGetProperty = purego.Dlsym(iokit, "IOHIDDeviceGetProperty") + procIOHIDManagerOpen = purego.Dlsym(iokit, "IOHIDManagerOpen") + procIOHIDManagerSetDeviceMatchingMultiple = purego.Dlsym(iokit, "IOHIDManagerSetDeviceMatchingMultiple") + procIOHIDManagerRegisterDeviceMatchingCallback = purego.Dlsym(iokit, "IOHIDManagerRegisterDeviceMatchingCallback") + procIOHIDManagerRegisterDeviceRemovalCallback = purego.Dlsym(iokit, "IOHIDManagerRegisterDeviceRemovalCallback") + procIOHIDManagerScheduleWithRunLoop = purego.Dlsym(iokit, "IOHIDManagerScheduleWithRunLoop") + procIOHIDElementGetType = purego.Dlsym(iokit, "IOHIDElementGetType") + procIOHIDElementGetUsage = purego.Dlsym(iokit, "IOHIDElementGetUsage") + procIOHIDElementGetUsagePage = purego.Dlsym(iokit, "IOHIDElementGetUsagePage") + procIOHIDElementGetLogicalMin = purego.Dlsym(iokit, "IOHIDElementGetLogicalMin") + procIOHIDElementGetLogicalMax = purego.Dlsym(iokit, "IOHIDElementGetLogicalMax") + procIOHIDDeviceGetValue = purego.Dlsym(iokit, "IOHIDDeviceGetValue") + procIOHIDValueGetIntegerValue = purego.Dlsym(iokit, "IOHIDValueGetIntegerValue") + procIOHIDDeviceCopyMatchingElements = purego.Dlsym(iokit, "IOHIDDeviceCopyMatchingElements") +) + +func _IOHIDElementGetTypeID() _CFTypeID { + ret, _, _ := purego.SyscallN(procIOHIDElementGetTypeID) + return _CFTypeID(ret) +} + +func _IOHIDManagerCreate(allocator _CFAllocatorRef, options _IOOptionBits) _IOHIDManagerRef { + ret, _, _ := purego.SyscallN(procIOHIDManagerCreate, uintptr(allocator), uintptr(options)) + return _IOHIDManagerRef(ret) +} + +func _IOHIDDeviceGetProperty(device _IOHIDDeviceRef, key _CFStringRef) _CFTypeRef { + ret, _, _ := purego.SyscallN(procIOHIDDeviceGetProperty, uintptr(device), uintptr(key)) + return _CFTypeRef(ret) +} + +func _IOHIDManagerOpen(manager _IOHIDManagerRef, options _IOOptionBits) _IOReturn { + ret, _, _ := purego.SyscallN(procIOHIDManagerOpen, uintptr(manager), uintptr(options)) + return _IOReturn(ret) +} + +func _IOHIDManagerSetDeviceMatchingMultiple(manager _IOHIDManagerRef, multiple _CFArrayRef) { + purego.SyscallN(procIOHIDManagerSetDeviceMatchingMultiple, uintptr(manager), uintptr(multiple)) +} + +func _IOHIDManagerRegisterDeviceMatchingCallback(manager _IOHIDManagerRef, callback _IOHIDDeviceCallback, context unsafe.Pointer) { + purego.SyscallN(procIOHIDManagerRegisterDeviceMatchingCallback, uintptr(manager), purego.NewCallback(callback), uintptr(context)) +} + +func _IOHIDManagerRegisterDeviceRemovalCallback(manager _IOHIDManagerRef, callback _IOHIDDeviceCallback, context unsafe.Pointer) { + purego.SyscallN(procIOHIDManagerRegisterDeviceRemovalCallback, uintptr(manager), purego.NewCallback(callback), uintptr(context)) +} + +func _IOHIDManagerScheduleWithRunLoop(manager _IOHIDManagerRef, runLoop _CFRunLoopRef, runLoopMode _CFStringRef) { + purego.SyscallN(procIOHIDManagerScheduleWithRunLoop, uintptr(manager), uintptr(runLoop), uintptr(runLoopMode)) +} + +func _IOHIDElementGetType(element _IOHIDElementRef) _IOHIDElementType { + ret, _, _ := purego.SyscallN(procIOHIDElementGetType, uintptr(element)) + return _IOHIDElementType(ret) +} + +func _IOHIDElementGetUsage(element _IOHIDElementRef) uint32 { + ret, _, _ := purego.SyscallN(procIOHIDElementGetUsage, uintptr(element)) + return uint32(ret) +} + +func _IOHIDElementGetUsagePage(element _IOHIDElementRef) uint32 { + ret, _, _ := purego.SyscallN(procIOHIDElementGetUsagePage, uintptr(element)) + return uint32(ret) +} + +func _IOHIDElementGetLogicalMin(element _IOHIDElementRef) _CFIndex { + ret, _, _ := purego.SyscallN(procIOHIDElementGetLogicalMin, uintptr(element)) + return _CFIndex(ret) +} + +func _IOHIDElementGetLogicalMax(element _IOHIDElementRef) _CFIndex { + ret, _, _ := purego.SyscallN(procIOHIDElementGetLogicalMax, uintptr(element)) + return _CFIndex(ret) +} + +func _IOHIDDeviceGetValue(device _IOHIDDeviceRef, element _IOHIDElementRef, pValue *_IOHIDValueRef) _IOReturn { + if pValue == nil { + panic("IOHID: pValue cannot be nil") + } + ret, _, _ := purego.SyscallN(procIOHIDDeviceGetValue, uintptr(device), uintptr(element), uintptr(unsafe.Pointer(pValue))) + return _IOReturn(ret) +} + +func _IOHIDValueGetIntegerValue(value _IOHIDValueRef) _CFIndex { + ret, _, _ := purego.SyscallN(procIOHIDValueGetIntegerValue, uintptr(value)) + return _CFIndex(ret) +} + +func _IOHIDDeviceCopyMatchingElements(device _IOHIDDeviceRef, matching _CFDictionaryRef, options _IOOptionBits) _CFArrayRef { + ret, _, _ := purego.SyscallN(procIOHIDDeviceCopyMatchingElements, uintptr(device), uintptr(matching), uintptr(options)) + return _CFArrayRef(ret) +} diff --git a/internal/gamepad/gamepad_darwin.go b/internal/gamepad/gamepad_darwin.go index e8344af38..4c229fc3e 100644 --- a/internal/gamepad/gamepad_darwin.go +++ b/internal/gamepad/gamepad_darwin.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "sort" + "strings" "sync" "time" "unsafe" @@ -28,43 +29,10 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/gamepaddb" ) -// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit -// -// #include -// #include -// -// static CFStringRef cfStringRefIOHIDVendorIDKey() { -// return CFSTR(kIOHIDVendorIDKey); -// } -// -// static CFStringRef cfStringRefIOHIDProductIDKey() { -// return CFSTR(kIOHIDProductIDKey); -// } -// -// static CFStringRef cfStringRefIOHIDVersionNumberKey() { -// return CFSTR(kIOHIDVersionNumberKey); -// } -// -// static CFStringRef cfStringRefIOHIDProductKey() { -// return CFSTR(kIOHIDProductKey); -// } -// -// static CFStringRef cfStringRefIOHIDDeviceUsagePageKey() { -// return CFSTR(kIOHIDDeviceUsagePageKey); -// } -// -// static CFStringRef cfStringRefIOHIDDeviceUsageKey() { -// return CFSTR(kIOHIDDeviceUsageKey); -// } -// -// void ebitenGamepadMatchingCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef device); -// void ebitenGamepadRemovalCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef device); -import "C" - type nativeGamepadsImpl struct { - hidManager C.IOHIDManagerRef - devicesToAdd []C.IOHIDDeviceRef - devicesToRemove []C.IOHIDDeviceRef + hidManager _IOHIDManagerRef + devicesToAdd []_IOHIDDeviceRef + devicesToRemove []_IOHIDDeviceRef devicesM sync.Mutex } @@ -73,82 +41,80 @@ func newNativeGamepadsImpl() nativeGamepads { } func (g *nativeGamepadsImpl) init(gamepads *gamepads) error { - var dicts []C.CFDictionaryRef + var dicts []_CFDictionaryRef - page := C.kHIDPage_GenericDesktop + page := kHIDPage_GenericDesktop for _, usage := range []uint{ - C.kHIDUsage_GD_Joystick, - C.kHIDUsage_GD_GamePad, - C.kHIDUsage_GD_MultiAxisController, + kHIDUsage_GD_Joystick, + kHIDUsage_GD_GamePad, + kHIDUsage_GD_MultiAxisController, } { - pageRef := C.CFNumberCreate(C.kCFAllocatorDefault, C.kCFNumberIntType, unsafe.Pointer(&page)) + pageRef := _CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, unsafe.Pointer(&page)) if pageRef == 0 { return errors.New("gamepad: CFNumberCreate returned nil") } - defer C.CFRelease(C.CFTypeRef(pageRef)) + defer _CFRelease(_CFTypeRef(pageRef)) - usageRef := C.CFNumberCreate(C.kCFAllocatorDefault, C.kCFNumberIntType, unsafe.Pointer(&usage)) + usageRef := _CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, unsafe.Pointer(&usage)) if usageRef == 0 { return errors.New("gamepad: CFNumberCreate returned nil") } - defer C.CFRelease(C.CFTypeRef(usageRef)) + defer _CFRelease(_CFTypeRef(usageRef)) - keys := []C.CFStringRef{ - C.cfStringRefIOHIDDeviceUsagePageKey(), - C.cfStringRefIOHIDDeviceUsageKey(), + keys := []_CFStringRef{ + _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDDeviceUsagePageKey, kCFStringEncodingUTF8), + _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDDeviceUsageKey, kCFStringEncodingUTF8), } - values := []C.CFNumberRef{ + values := []_CFNumberRef{ pageRef, usageRef, } - dict := C.CFDictionaryCreate(C.kCFAllocatorDefault, + dict := _CFDictionaryCreate(kCFAllocatorDefault, (*unsafe.Pointer)(unsafe.Pointer(&keys[0])), (*unsafe.Pointer)(unsafe.Pointer(&values[0])), - C.CFIndex(len(keys)), &C.kCFTypeDictionaryKeyCallBacks, &C.kCFTypeDictionaryValueCallBacks) + _CFIndex(len(keys)), *(**_CFDictionaryKeyCallBacks)(unsafe.Pointer(&kCFTypeDictionaryKeyCallBacks)), *(**_CFDictionaryValueCallBacks)(unsafe.Pointer(&kCFTypeDictionaryValueCallBacks))) if dict == 0 { return errors.New("gamepad: CFDictionaryCreate returned nil") } - defer C.CFRelease(C.CFTypeRef(dict)) + defer _CFRelease(_CFTypeRef(dict)) dicts = append(dicts, dict) } - matching := C.CFArrayCreate(C.kCFAllocatorDefault, + matching := _CFArrayCreate(kCFAllocatorDefault, (*unsafe.Pointer)(unsafe.Pointer(&dicts[0])), - C.CFIndex(len(dicts)), &C.kCFTypeArrayCallBacks) + _CFIndex(len(dicts)), *(**_CFArrayCallBacks)(unsafe.Pointer(&kCFTypeArrayCallBacks))) if matching == 0 { return errors.New("gamepad: CFArrayCreateMutable returned nil") } - defer C.CFRelease(C.CFTypeRef(matching)) + defer _CFRelease(_CFTypeRef(matching)) - g.hidManager = C.IOHIDManagerCreate(C.kCFAllocatorDefault, C.kIOHIDOptionsTypeNone) - if C.IOHIDManagerOpen(g.hidManager, C.kIOHIDOptionsTypeNone) != C.kIOReturnSuccess { + g.hidManager = _IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone) + if _IOHIDManagerOpen(g.hidManager, kIOHIDOptionsTypeNone) != kIOReturnSuccess { return errors.New("gamepad: IOHIDManagerOpen failed") } - C.IOHIDManagerSetDeviceMatchingMultiple(g.hidManager, matching) - C.IOHIDManagerRegisterDeviceMatchingCallback(g.hidManager, C.IOHIDDeviceCallback(C.ebitenGamepadMatchingCallback), nil) - C.IOHIDManagerRegisterDeviceRemovalCallback(g.hidManager, C.IOHIDDeviceCallback(C.ebitenGamepadRemovalCallback), nil) + _IOHIDManagerSetDeviceMatchingMultiple(g.hidManager, matching) + _IOHIDManagerRegisterDeviceMatchingCallback(g.hidManager, ebitenGamepadMatchingCallback, nil) + _IOHIDManagerRegisterDeviceRemovalCallback(g.hidManager, ebitenGamepadRemovalCallback, nil) - C.IOHIDManagerScheduleWithRunLoop(g.hidManager, C.CFRunLoopGetMain(), C.kCFRunLoopDefaultMode) + _IOHIDManagerScheduleWithRunLoop(g.hidManager, _CFRunLoopGetMain(), **(**_CFStringRef)(unsafe.Pointer(&kCFRunLoopDefaultMode))) // Execute the run loop once in order to register any initially-attached gamepads. - C.CFRunLoopRunInMode(C.kCFRunLoopDefaultMode, 0, 0 /* false */) + _CFRunLoopRunInMode(**(**_CFStringRef)(unsafe.Pointer(&kCFRunLoopDefaultMode)), 0, false) return nil } -//export ebitenGamepadMatchingCallback -func ebitenGamepadMatchingCallback(ctx unsafe.Pointer, res C.IOReturn, sender unsafe.Pointer, device C.IOHIDDeviceRef) { +func ebitenGamepadMatchingCallback(ctx unsafe.Pointer, res _IOReturn, sender unsafe.Pointer, device _IOHIDDeviceRef) { n := theGamepads.native.(*nativeGamepadsImpl) n.devicesM.Lock() defer n.devicesM.Unlock() n.devicesToAdd = append(n.devicesToAdd, device) } -//export ebitenGamepadRemovalCallback -func ebitenGamepadRemovalCallback(ctx unsafe.Pointer, res C.IOReturn, sender unsafe.Pointer, device C.IOHIDDeviceRef) { +func ebitenGamepadRemovalCallback(ctx unsafe.Pointer, res _IOReturn, sender unsafe.Pointer, device _IOHIDDeviceRef) { n := theGamepads.native.(*nativeGamepadsImpl) n.devicesM.Lock() defer n.devicesM.Unlock() @@ -173,7 +139,7 @@ func (g *nativeGamepadsImpl) update(gamepads *gamepads) error { return nil } -func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepads) { +func (g *nativeGamepadsImpl) addDevice(device _IOHIDDeviceRef, gamepads *gamepads) { if gamepads.find(func(g *Gamepad) bool { return g.native.(*nativeGamepadImpl).device == device }) != nil { @@ -181,25 +147,25 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa } name := "Unknown" - if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDProductKey()); prop != 0 { - var cstr [256]C.char - C.CFStringGetCString(C.CFStringRef(prop), &cstr[0], C.CFIndex(len(cstr)), C.kCFStringEncodingUTF8) - name = C.GoString(&cstr[0]) + if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductKey, kCFStringEncodingUTF8)); prop != 0 { + var cstr [256]byte + _CFStringGetCString(_CFStringRef(prop), cstr[:], kCFStringEncodingUTF8) + name = strings.TrimRight(string(cstr[:]), "\x00") } var vendor uint32 - if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDVendorIDKey()); prop != 0 { - C.CFNumberGetValue(C.CFNumberRef(prop), C.kCFNumberSInt32Type, unsafe.Pointer(&vendor)) + if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDVendorIDKey, kCFStringEncodingUTF8)); prop != 0 { + _CFNumberGetValue(_CFNumberRef(prop), kCFNumberSInt32Type, unsafe.Pointer(&vendor)) } var product uint32 - if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDProductIDKey()); prop != 0 { - C.CFNumberGetValue(C.CFNumberRef(prop), C.kCFNumberSInt32Type, unsafe.Pointer(&product)) + if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductIDKey, kCFStringEncodingUTF8)); prop != 0 { + _CFNumberGetValue(_CFNumberRef(prop), kCFNumberSInt32Type, unsafe.Pointer(&product)) } var version uint32 - if prop := C.IOHIDDeviceGetProperty(device, C.cfStringRefIOHIDVersionNumberKey()); prop != 0 { - C.CFNumberGetValue(C.CFNumberRef(prop), C.kCFNumberSInt32Type, unsafe.Pointer(&version)) + if prop := _IOHIDDeviceGetProperty(_IOHIDDeviceRef(device), _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDVersionNumberKey, kCFStringEncodingUTF8)); prop != 0 { + _CFNumberGetValue(_CFNumberRef(prop), kCFNumberSInt32Type, unsafe.Pointer(&version)) } var sdlID string @@ -217,8 +183,8 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7], bs[8], bs[9], bs[10], bs[11]) } - elements := C.IOHIDDeviceCopyMatchingElements(device, 0, C.kIOHIDOptionsTypeNone) - defer C.CFRelease(C.CFTypeRef(elements)) + elements := _IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone) + defer _CFRelease(_CFTypeRef(elements)) n := &nativeGamepadImpl{ device: device, @@ -226,71 +192,71 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa gp := gamepads.add(name, sdlID) gp.native = n - for i := C.CFIndex(0); i < C.CFArrayGetCount(elements); i++ { - native := (C.IOHIDElementRef)(C.CFArrayGetValueAtIndex(elements, i)) - if C.CFGetTypeID(C.CFTypeRef(native)) != C.IOHIDElementGetTypeID() { + for i := _CFIndex(0); i < _CFArrayGetCount(_CFArrayRef(elements)); i++ { + native := (_IOHIDElementRef)(_CFArrayGetValueAtIndex(_CFArrayRef(elements), i)) + if _CFGetTypeID(_CFTypeRef(native)) != _IOHIDElementGetTypeID() { continue } - typ := C.IOHIDElementGetType(native) - if typ != C.kIOHIDElementTypeInput_Axis && - typ != C.kIOHIDElementTypeInput_Button && - typ != C.kIOHIDElementTypeInput_Misc { + typ := _IOHIDElementGetType(native) + if typ != kIOHIDElementTypeInput_Axis && + typ != kIOHIDElementTypeInput_Button && + typ != kIOHIDElementTypeInput_Misc { continue } - usage := C.IOHIDElementGetUsage(native) - page := C.IOHIDElementGetUsagePage(native) + usage := _IOHIDElementGetUsage(native) + page := _IOHIDElementGetUsagePage(native) switch page { - case C.kHIDPage_GenericDesktop: + case kHIDPage_GenericDesktop: switch usage { - case C.kHIDUsage_GD_X, C.kHIDUsage_GD_Y, C.kHIDUsage_GD_Z, - C.kHIDUsage_GD_Rx, C.kHIDUsage_GD_Ry, C.kHIDUsage_GD_Rz, - C.kHIDUsage_GD_Slider, C.kHIDUsage_GD_Dial, C.kHIDUsage_GD_Wheel: + case kHIDUsage_GD_X, kHIDUsage_GD_Y, kHIDUsage_GD_Z, + kHIDUsage_GD_Rx, kHIDUsage_GD_Ry, kHIDUsage_GD_Rz, + kHIDUsage_GD_Slider, kHIDUsage_GD_Dial, kHIDUsage_GD_Wheel: n.axes = append(n.axes, element{ native: native, usage: int(usage), index: len(n.axes), - minimum: int(C.IOHIDElementGetLogicalMin(native)), - maximum: int(C.IOHIDElementGetLogicalMax(native)), + minimum: int(_IOHIDElementGetLogicalMin(native)), + maximum: int(_IOHIDElementGetLogicalMax(native)), }) - case C.kHIDUsage_GD_Hatswitch: + case kHIDUsage_GD_Hatswitch: n.hats = append(n.hats, element{ native: native, usage: int(usage), index: len(n.hats), - minimum: int(C.IOHIDElementGetLogicalMin(native)), - maximum: int(C.IOHIDElementGetLogicalMax(native)), + minimum: int(_IOHIDElementGetLogicalMin(native)), + maximum: int(_IOHIDElementGetLogicalMax(native)), }) - case C.kHIDUsage_GD_DPadUp, C.kHIDUsage_GD_DPadRight, C.kHIDUsage_GD_DPadDown, C.kHIDUsage_GD_DPadLeft, - C.kHIDUsage_GD_SystemMainMenu, C.kHIDUsage_GD_Select, C.kHIDUsage_GD_Start: + case kHIDUsage_GD_DPadUp, kHIDUsage_GD_DPadRight, kHIDUsage_GD_DPadDown, kHIDUsage_GD_DPadLeft, + kHIDUsage_GD_SystemMainMenu, kHIDUsage_GD_Select, kHIDUsage_GD_Start: n.buttons = append(n.buttons, element{ native: native, usage: int(usage), index: len(n.buttons), - minimum: int(C.IOHIDElementGetLogicalMin(native)), - maximum: int(C.IOHIDElementGetLogicalMax(native)), + minimum: int(_IOHIDElementGetLogicalMin(native)), + maximum: int(_IOHIDElementGetLogicalMax(native)), }) } - case C.kHIDPage_Simulation: + case kHIDPage_Simulation: switch usage { - case C.kHIDUsage_Sim_Accelerator, C.kHIDUsage_Sim_Brake, C.kHIDUsage_Sim_Throttle, C.kHIDUsage_Sim_Rudder, C.kHIDUsage_Sim_Steering: + case kHIDUsage_Sim_Accelerator, kHIDUsage_Sim_Brake, kHIDUsage_Sim_Throttle, kHIDUsage_Sim_Rudder, kHIDUsage_Sim_Steering: n.axes = append(n.axes, element{ native: native, usage: int(usage), index: len(n.axes), - minimum: int(C.IOHIDElementGetLogicalMin(native)), - maximum: int(C.IOHIDElementGetLogicalMax(native)), + minimum: int(_IOHIDElementGetLogicalMin(native)), + maximum: int(_IOHIDElementGetLogicalMax(native)), }) } - case C.kHIDPage_Button, C.kHIDPage_Consumer: + case kHIDPage_Button, kHIDPage_Consumer: n.buttons = append(n.buttons, element{ native: native, usage: int(usage), index: len(n.buttons), - minimum: int(C.IOHIDElementGetLogicalMin(native)), - maximum: int(C.IOHIDElementGetLogicalMax(native)), + minimum: int(_IOHIDElementGetLogicalMin(native)), + maximum: int(_IOHIDElementGetLogicalMax(native)), }) } } @@ -301,7 +267,7 @@ func (g *nativeGamepadsImpl) addDevice(device C.IOHIDDeviceRef, gamepads *gamepa } type element struct { - native C.IOHIDElementRef + native _IOHIDElementRef usage int index int minimum int @@ -329,7 +295,7 @@ func (e elements) Swap(i, j int) { } type nativeGamepadImpl struct { - device C.IOHIDDeviceRef + device _IOHIDDeviceRef axes elements buttons elements hats elements @@ -340,11 +306,10 @@ type nativeGamepadImpl struct { } func (g *nativeGamepadImpl) elementValue(e *element) int { - var valueRef C.IOHIDValueRef - if C.IOHIDDeviceGetValue(g.device, e.native, &valueRef) == C.kIOReturnSuccess { - return int(C.IOHIDValueGetIntegerValue(valueRef)) + var valueRef _IOHIDValueRef + if _IOHIDDeviceGetValue(g.device, e.native, &valueRef) == kIOReturnSuccess { + return int(_IOHIDValueGetIntegerValue(valueRef)) } - return 0 }