Closed kyods closed 3 years ago
Are you using an XBox-S-Controller? I am asking because macOS completely ignores my own Xbox controller (even if connected by cable).
I use exactly this model: https://www.xbox.com/en-US/accessories/controllers/phantom-white - and it works perfectly in macOS, both Catalina and Big Sur.
I've added the controller to the list of yet unsupported controllers, so it won't be forgotten:
@kyods: Thank you very much for your kind donation, which arrived just in time for Christmas. I have already analyzed the USB messages from the controller and made the appropriate adjustments in the GameController class. In v0.9.16 the controller is recognized and both the two analog sticks and the hatswitch should work. Please let me know if there is any issue left with the support of this controller.
BTW, the controller should be displayed as „XBox Carbon Black“. If not, it is not recognized correctly (due to a different product ID of your model and mine):
Hi Dirk,
I'm glad I could help - and I was quite amazed (pun intended) about Amazon delivering so quickly. The bad news, however, is that I'm still having issues with my controller not being recognised. vAmiga doesn't recognise the DualShock 4 controller I borrowed from a friend either, which makes me think there might be something happening on my side - although both controllers work in VirtualC64. To make things even weirder, vAmiga is showing the generic "mouse" USB device available even when there's nothing connected neither via Bluetooth nor USB. Odd.
Amazon delivering so quickly
Sadly, this is one of the rare things still working here 🥴.
To tackle the remaining issues, I think it's best to come up with a more general solution. Since most controllers seem to map events based on one of a limited number of schemes, I'll try to make these schemes configurable in the configuration panel. I'll also display the important USB device information such as the vendor ID and product ID. Doing so will enable us to debug these things without buying each and every controller.
In the next version, external HID devices will be customizable by selecting predefined mapping schemes for the left stick, right stick, and hat switch.
It's not fully functional, yet. I'll follow up on that after the Christmas break.
The panel is (supposed to be) fully functional in v0.9.16.1.
Can you connect the unrecognised DualShock 4 controller and make a screenshot? I can then compare the values with the ones in the database.
Here's the weird thing: vAmiga doesn't recognise any controllers I connect via Bluetooth, neither the DualShock 4, nor the Xbox One controller. The only device it recognises is the built-in trackpad, which doesn't seem right:
I do have an external Magic Trackpad which I use when I connect my Macbook to the monitor, and I had a feeling that this is what might be confusing vAmiga, or interfering with the device detection. There might be a hint of truth in that, because when I switched the trackpad on (I keep it off when detached from the monitor), the device selection drop-down list went bonkers:
For the testing purposes I removed the trackpad from my Bluetooth devices, rebooted and started vAmiga again, but that didn't make the situation any different.
Let me know please if there's anything else I can do on my end to assist.
The only device it recognises is the built-in trackpad, which doesn't seem right:
The HID manager presents the internal trackpad to vAmiga every time. Normally, vAmiga filters the trackpad out as it does with every other device that is marked as "build-in". Maybe the device we see here is the external trackpad which itself identifies as internal trackpad. Apple does something similar with mice. It's extremely hard to distinguish the internal mouse from an external one (simply because Apple doesn't want us to distinguish them).
the device selection drop-down list went bonkers:
😳 Uh, this shouldn't be possible. For some reason, the device slots get overwritten. However, the emulator is not supposed to modify the first three slots at all (or four if "None" is considered a device slot).
Edit: VirtualC64 does not recognize the trackpad, because it filters out all HID devices of type "mouse". vAmiga is able to support external mice, VirtualC64 is not (because mice aren't as important on the C64 as they are on the Amiga).
Is it possible that the device filtering might be somehow getting in the way? I can't really imagine why that would be happening only in my setup, though. Anyway, I can see both controllers just fine in VirtualC64 (although the Xbox controller uses the generic name):
Hmm, VirtualC64 (3.4) gets it right (the new version will likely fail, too, because it uses the same codes as vAmiga).
It's hard to debug remotely. Are you familiar with Xode? If it's possible for you to compile and run vAmiga inside Xcode, the following function would be the entry point (in GamePadManager.swift):
//
// HID support
//
// Matching callback (invoked when a matching HID device is plugged in)
func hidDeviceAdded(context: UnsafeMutableRawPointer?,
result: IOReturn,
sender: UnsafeMutableRawPointer?,
device: IOHIDDevice) {
track()
// Ignore internal devices
if device.isBuiltIn { return }
// Find a free slot for the new device
guard let slot = findFreeSlot() else { return }
// Add device
addDevice(slot: slot, device: device)
// Reconnect devices (assignments trigger side effects)
parent.config.gameDevice1 = parent.config.gameDevice1
parent.config.gameDevice2 = parent.config.gameDevice2
// Inform about the changed configuration
parent.toolbar.validateVisibleItems()
parent.myAppDelegate.deviceAdded()
listDevices()
}
Debug messages can be produced via track()
. Here, it would be interesting to see if the function is called at all, and if yes, if it executes all down the way until listDevices()
is called (which produces more debug messages in the Xcode console window).
Filtering is done in init(parent: )
with the following list:
// Prepare to accept HID devices
let deviceCriteria = [
[
kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop,
kIOHIDDeviceUsageKey: kHIDUsage_GD_Joystick
],
[
kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop,
kIOHIDDeviceUsageKey: kHIDUsage_GD_GamePad
],
[
kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop,
kIOHIDDeviceUsageKey: kHIDUsage_GD_MultiAxisController
],
[
kIOHIDDeviceUsagePageKey: kHIDPage_GenericDesktop,
kIOHIDDeviceUsageKey: kHIDUsage_GD_Mouse
]
]
vAmiga accepts more devices than VirtualC64. Hence, it's unlikely that your controller is filtered out here.Nevertheless, it would be interesting to see how the emulator reacts if kHIDUsage_GD_Mouse
devices are removed from that list. Your trackpad should no longer show up in the emulator in this case.
My only experience with Xcode so far was a failed attempt at compiling Madd's fork of Boxer https://github.com/MaddTheSane/Boxer. I am willing to reinstall Xcode and give it a try, though, but you would need to guide me step by step, and since I am a total layman, our mileage may vary.
I am willing to reinstall Xcode and give it a try
Great. You can compile it just as VirtualC64 which was discussed in an older thread here. If everything works as expected, it's basically downloading the project, launching Xcode and hitting "Run":
https://github.com/dirkwhoffmann/virtualc64/issues/566
If compilation should go wrong, I am sure we can easily rule out the issues.
Sounds like an adventure. I'll install XCode tonight and try to compile vAmiga tomorrow.
Well, mission accomplished. I have managed to built and run vAmiga in Xcode. Here's what I see in the console log upon startup with the DualShock 4 connected via Bluetooth:
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
MyController.301::addListener()
MyController.321::createTimer()
MyAppDelegate.53::applicationDidFinishLaunching(_:)
MyControllerTouchBar.44::makeTouchBar()
GamePadManager.169::hidDeviceAdded(context:result:sender:device:)
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [-] v: 1452 p: 631 l: 16777216 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
MyAppDelegate.176::deviceAdded()
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
GamePadManager.169::hidDeviceAdded(context:result:sender:device:)
MyDocument.380::loadScreenshots(): Seeking screenshots for disk with id 0
MyDocument.389::loadScreenshots(): 0 screenshots loaded
MyController.446::processMessage(_:): Registered to message queue
Animation.197::zoomIn(steps:): Zooming in...
2020-12-28 16:35:29.254553+0100 vAmiga[35757:1563221] [aqme] AQMEIO.cpp:182:AwaitIOCycle: timed out after 0.012s (16 17); suspension count=0 (IOSuspensions: )
Well, mission accomplished
Very good. I can spot two calls to hidDeviceAdded
in your log. The first one is for your internal / external trackpad. The second one is for the unrecognised DualShock 4. In the second call the function is exited earlier, because I can't see the result of listDevices()
in the log. Now, we need to find out where the functions exists. To find out, simply place track() statements in each blank line in the following function and run again (File GamePadManager.swift). The log will show where the function exits.
func hidDeviceAdded(context: UnsafeMutableRawPointer?,
result: IOReturn,
sender: UnsafeMutableRawPointer?,
device: IOHIDDevice) {
track()
// Ignore internal devices
if device.isBuiltIn { return }
// Find a free slot for the new device
guard let slot = findFreeSlot() else { return }
// Add device
addDevice(slot: slot, device: device)
// Reconnect devices (assignments trigger side effects)
parent.config.gameDevice1 = parent.config.gameDevice1
parent.config.gameDevice2 = parent.config.gameDevice2
// Inform about the changed configuration
parent.toolbar.validateVisibleItems()
parent.myAppDelegate.deviceAdded()
listDevices()
}
Not sure if I did it right, but here we go:
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
MyController.301::addListener()
MyController.321::createTimer()
MyControllerTouchBar.44::makeTouchBar()
GamePadManager.169::hidDeviceAdded(context:result:sender:device:)
GamePadManager.169::hidDeviceAdded(context:result:sender:device:)
GamePadManager.173::hidDeviceAdded(context:result:sender:device:)
GamePadManager.176::hidDeviceAdded(context:result:sender:device:)
GamePadManager.179::hidDeviceAdded(context:result:sender:device:)
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [-] v: 1452 p: 631 l: 16777216 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
GamePadManager.183::hidDeviceAdded(context:result:sender:device:)
MyAppDelegate.176::deviceAdded()
GamePadManager.187::hidDeviceAdded(context:result:sender:device:)
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
MyDocument.380::loadScreenshots(): Seeking screenshots for disk with id 0
MyDocument.389::loadScreenshots(): 0 screenshots loaded
MyController.446::processMessage(_:): Registered to message queue
Animation.197::zoomIn(steps:): Zooming in...
2020-12-28 17:20:59.717732+0100 vAmiga[36134:1590803] [aqme] AQMEIO.cpp:182:AwaitIOCycle: timed out after 0.012s (16 17); suspension count=0 (IOSuspensions: )
GamePadManager.169::hidDeviceAdded(context:result:sender:device:)
GamePadManager.169::hidDeviceAdded(context:result:sender:device:)
What we see in the log here is a strong indication of a multi-threading issue. In the next release, I'll add a lock to synchronise calls. With some luck, this is going to fix the issue.
I've checked in a potential fix on the main branch. Could you download the latest code and compile it in Xcode as you did before?
What I did is to add a NSLock to the GamePadManager:
var lock = NSLock()
This lock is utilised in function hidDeviceAdded as follows:
func hidDeviceAdded(context: UnsafeMutableRawPointer?,
result: IOReturn,
sender: UnsafeMutableRawPointer?,
device: IOHIDDevice) {
lock.lock(); defer { lock.unlock() }
...
Now, all devices should be processed one after another.
Unfortunately still no go.
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
MyController.301::addListener()
MyController.321::createTimer()
MyControllerTouchBar.44::makeTouchBar()
GamePadManager.168::hidDeviceAdded(context:result:sender:device:)
GamePadManager.172::hidDeviceAdded(context:result:sender:device:)
GamePadManager.175::hidDeviceAdded(context:result:sender:device:)
GamePadManager.178::hidDeviceAdded(context:result:sender:device:)
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [-] v: 1452 p: 631 l: 16777216 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
GamePadManager.182::hidDeviceAdded(context:result:sender:device:)
MyAppDelegate.176::deviceAdded()
GamePadManager.186::hidDeviceAdded(context:result:sender:device:)
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
GamePadManager.168::hidDeviceAdded(context:result:sender:device:)
MyDocument.380::loadScreenshots(): Seeking screenshots for disk with id 0
MyDocument.389::loadScreenshots(): 0 screenshots loaded
MyController.446::processMessage(_:): Registered to message queue
Animation.197::zoomIn(steps:): Zooming in...
Although it's not working as expected yet, we can see in the log that the lock is doing what it is supposed to do. Let's try to produce more debug output. Could you replace function hidDeviceAdded by the following code and run again? The new code will print out all property keys for all devices that are accepted by the HID handler.
func hidDeviceAdded(context: UnsafeMutableRawPointer?,
result: IOReturn,
sender: UnsafeMutableRawPointer?,
device: IOHIDDevice) {
lock.lock(); defer { lock.unlock() }
track("Processing device:")
device.listProperties()
// Ignore internal devices
if device.isBuiltIn {
track("Skipping this device")
return
}
track("External device")
// Find a free slot for the new device
guard let slot = findFreeSlot() else { return }
track("slot =\(slot)")
// Add device
addDevice(slot: slot, device: device)
track("Added")
// Reconnect devices (assignments trigger side effects)
parent.config.gameDevice1 = parent.config.gameDevice1
parent.config.gameDevice2 = parent.config.gameDevice2
track("Reconnected")
// Inform about the changed configuration
parent.toolbar.validateVisibleItems()
parent.myAppDelegate.deviceAdded()
listDevices()
track("Done")
}
Done. Somewhere down there I see my DualShock 4, and unless I'm confusing things, vAmiga identifies is as a built-in device?
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
MyController.301::addListener()
MyController.321::createTimer()
MyControllerTouchBar.44::makeTouchBar()
GamePadManager.168::hidDeviceAdded(context:result:sender:device:): Processing device:
Transport: SPI
VendorID: 1452
ProductID: 631
VersionNumber: 2198
Product: Apple Internal Keyboard / Trackpad
CountryCode: 0
LocationID: 16777216
DeviceUsagePairs: (
{
DeviceUsage = 2;
DeviceUsagePage = 1;
},
{
DeviceUsage = 1;
DeviceUsagePage = 1;
},
{
DeviceUsage = 5;
DeviceUsagePage = 13;
},
{
DeviceUsage = 12;
DeviceUsagePage = 65280;
}
)
PrimaryUsage: 2
PrimaryUsagePage: 1
MaxInputReportSize: 1368
MaxOutputReportSize: 1
MaxFeatureReportSize: 1
ReportInterval: 8000
ReportDescriptor: {length = 110, bytes = 0x05010902 a1010901 a1000509 19012903 ... 75089657 058100c0 }
UniqueID: 4295071364
GamePadManager.176::hidDeviceAdded(context:result:sender:device:): External device
GamePadManager.180::hidDeviceAdded(context:result:sender:device:): slot =3
GamePadManager.184::hidDeviceAdded(context:result:sender:device:): Added
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [-] v: 1452 p: 631 l: 16777216 48 49 53 50 0
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
GamePadManager.189::hidDeviceAdded(context:result:sender:device:): Reconnected
MyAppDelegate.176::deviceAdded()
Input devices:
Mouse (Mouse) [1] 48 49 53 50 0
Joystick Keyset 1 [-] 48 49 53 50 0
Joystick Keyset 2 [-] 48 49 53 50 0
Apple Internal Keyboard / Trackpad (Mouse) [2] v: 1452 p: 631 l: 16777216 48 49 53 50 0
GamePadManager.196::hidDeviceAdded(context:result:sender:device:): Done
GamePadManager.168::hidDeviceAdded(context:result:sender:device:): Processing device:
Transport: Bluetooth
VendorID: 1356
VendorIDSource: 2
ProductID: 2508
VersionNumber: 256
Manufacturer: Unknown
Product: DUALSHOCK 4 Wireless Controller
SerialNumber: a4-ae-12-e7-fd-33
CountryCode: 0
LocationID: 317193523
DeviceUsagePairs: (
{
DeviceUsage = 5;
DeviceUsagePage = 1;
}
)
PrimaryUsage: 5
PrimaryUsagePage: 1
MaxInputReportSize: 547
MaxOutputReportSize: 547
MaxFeatureReportSize: 64
ReportInterval: 11250
ReportDescriptor: {length = 442, bytes = 0x05010905 a1018501 09300931 09320935 ... 0285d409 44b102c0 }
Built-In: 1
UniqueID: 4295072039
GamePadManager.173::hidDeviceAdded(context:result:sender:device:): Skipping this device
MyDocument.380::loadScreenshots(): Seeking screenshots for disk with id 0
MyDocument.389::loadScreenshots(): 0 screenshots loaded
MyController.446::processMessage(_:): Registered to message queue
Animation.197::zoomIn(steps:): Zooming in...
2020-12-29 15:54:37.346969+0100 vAmiga[39139:1743375] [aqme] AQMEIO.cpp:182:AwaitIOCycle: timed out after 0.012s (16 17); suspension count=0 (IOSuspensions: )
OK, now we know what the problem is:
Built-In: 1
The HID manager presents the DualShock 4 to the emulator as a built-in device on your machine. I have no idea how this is possible. Either I misinterpret the semantics of a "built-in" device or it's a macOS bug. As a workaround, we could consider all Bluetooth devices as external and ignore the built-in flag in that case. 🤔
I think that's a good strategy, and we can safely assume that something connecting via Bluetooth cannot at the same time be built-in. :)
Your DualShock controller should be detected in v0.9.16.2 (hopefully).
Works beautifully.
Now that we know what the issue is, I hope that fixing the Xbox controller wouldn't prove too much of a hassle?
EDIT: Scratch that. The Xbox controller works like a charm too - although not at the same time with the DualShock. Excellent work, thanks a lot, Dirk!
Hi Dirk,
I can't get my Xbox One Wireless Controller to work in vAmiga. The odd thing is that it works fine in Virtual C64 (at least the analogue stick, the D-Pad behaves like if the "up" button was being constantly pressed). Thanks in advance for looking into this.