internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate) { // If the device isn't a WebGL device, we're not interested. if (string.Compare(description.interfaceName, InterfaceName, StringComparison.InvariantCultureIgnoreCase) != 0) { return(null); } // If it was matched by the standard mapping, we don't need to fall back to generating a layout. if (!string.IsNullOrEmpty(matchedLayout) && matchedLayout != "Gamepad") { return(null); } var deviceMatcher = InputDeviceMatcher.FromDeviceDescription(description); var layout = new WebGLLayoutBuilder { capabilities = WebGLDeviceCapabilities.FromJson(description.capabilities) }; InputSystem.RegisterLayoutBuilder(() => layout.Build(), description.product, "Joystick", deviceMatcher); return(description.product); }
Minis.MidiDevice Search() { // Matcher object with Minis devices var match = new InputDeviceMatcher().WithInterface("Minis"); // Product name specifier if (!string.IsNullOrEmpty(_productName)) { match = match.WithProduct(_productName); } // Channel number specifier with a capability match if (_channel >= 0 && _channel < 16) { match = match.WithCapability("channel", _channel); } // Scan all the devices found in the input system. foreach (var dev in InputSystem.devices) { if (match.MatchPercentage(dev.description) > 0) { return((Minis.MidiDevice)dev); } } return(null); }
public static void SelfRegister() { InputDeviceMatcher matcher = new InputDeviceMatcher(). WithInterface("HID"). WithCapability("vendorId", 0x0f0d). WithCapability("productId", 0xc1); InputSystem.RegisterLayout <HORIPADSwitchController>("HORIPAD Switch Controller", matches: matcher); }
public static void SelfRegister() { InputDeviceMatcher matcher = new InputDeviceMatcher(). WithInterface("HID"). WithCapability("vendorId", 0x20d6). WithCapability("productId", 0xa711); InputSystem.RegisterLayout <PowerACorePlusController>("PowerA Core (Plus) Controller", matches: matcher); }
public static void SelfRegister() { var mayflashAdapter = new InputDeviceMatcher().WithInterface("HID").WithCapability("vendorId", 0x0079); InputSystem.RegisterLayout <GameCubeController>(matches: mayflashAdapter); var weeWuGCAdapter = new InputDeviceMatcher().WithInterface("HID").WithCapability("vendorId", 0x057E).WithProduct("0x0337"); InputSystem.RegisterLayout <GameCubeController>(matches: weeWuGCAdapter); }
// This is the workhorse for figuring out fallback options for HIDs attached to the system. // If the system cannot find a more specific layout for a given HID, this method will try // to produce a layout builder on the fly based on the HID descriptor received from // the device. internal static string OnFindLayoutForDevice(int deviceId, ref InputDeviceDescription description, string matchedLayout, IInputRuntime runtime) { // If the system found a matching layout, there's nothing for us to do. if (!string.IsNullOrEmpty(matchedLayout)) { return(null); } // If the device isn't a HID, we're not interested. if (description.interfaceName != kHIDInterface) { return(null); } // Read HID descriptor. var hidDeviceDescriptor = ReadHIDDeviceDescriptor(deviceId, ref description, runtime); // Determine if there's any usable elements on the device. var hasUsableElements = false; if (hidDeviceDescriptor.elements != null) { foreach (var element in hidDeviceDescriptor.elements) { if (element.DetermineLayout() != null) { hasUsableElements = true; break; } } } // If not, there's nothing we can do with the device. if (!hasUsableElements) { return(null); } // Determine base layout. var baseLayout = "HID"; if (hidDeviceDescriptor.usagePage == UsagePage.GenericDesktop) { /* * ////TODO: there's some work to be done to make the HID *actually* compatible with these devices * if (hidDeviceDescriptor.usage == (int)GenericDesktop.Joystick) * baseLayout = "Joystick"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Gamepad) * baseLayout = "Gamepad"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Mouse) * baseLayout = "Mouse"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Pointer) * baseLayout = "Pointer"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Keyboard) * baseLayout = "Keyboard"; */ } ////TODO: match HID layouts by vendor and product ID ////REVIEW: this probably works fine for most products out there but I'm not sure it works reliably for all cases // Come up with a unique template name. HIDs are required to have product and vendor IDs. // We go with the string versions if we have them and with the numeric versions if we don't. string layoutName; if (!string.IsNullOrEmpty(description.product) && !string.IsNullOrEmpty(description.manufacturer)) { layoutName = string.Format("{0}::{1} {2}", kHIDNamespace, description.manufacturer, description.product); } else { // Sanity check to make sure we really have the data we expect. if (hidDeviceDescriptor.vendorId == 0) { return(null); } layoutName = string.Format("{0}::{1:X}-{2:X}", kHIDNamespace, hidDeviceDescriptor.vendorId, hidDeviceDescriptor.productId); } // Register layout builder that will turn the HID descriptor into an // InputControlLayout instance. var layout = new HIDLayoutBuilder { hidDescriptor = hidDeviceDescriptor }; InputSystem.RegisterLayoutBuilder(() => layout.Build(), layoutName, baseLayout, InputDeviceMatcher.FromDeviceDescription(description)); return(layoutName); }
internal static string OnFindLayoutForDevice(int deviceId, ref InputDeviceDescription description, string matchedLayout, IInputRuntime runtime) { // If the device isn't a XRInput, we're not interested. if (description.interfaceName != XRUtilities.kXRInterfaceCurrent && description.interfaceName != XRUtilities.kXRInterfaceV1) { return(null); } // If the description doesn't come with a XR SDK descriptor, we're not // interested either. if (string.IsNullOrEmpty(description.capabilities)) { return(null); } // Try to parse the XR descriptor. XRDeviceDescriptor deviceDescriptor; try { deviceDescriptor = XRDeviceDescriptor.FromJson(description.capabilities); } catch (Exception) { return(null); } if (deviceDescriptor == null) { return(null); } if (string.IsNullOrEmpty(matchedLayout)) { if (deviceDescriptor.deviceRole == DeviceRole.LeftHanded || deviceDescriptor.deviceRole == DeviceRole.RightHanded) { matchedLayout = "XRController"; } else if (deviceDescriptor.deviceRole == DeviceRole.Generic) { matchedLayout = "XRHMD"; } } string layoutName = null; if (string.IsNullOrEmpty(description.manufacturer)) { layoutName = string.Format("{0}::{1}", SanitizeName(description.interfaceName), SanitizeName(description.product)); } else { layoutName = string.Format("{0}::{1}::{2}", SanitizeName(description.interfaceName), SanitizeName(description.manufacturer), SanitizeName(description.product)); } // If we are already using a generated layout, we just want to use what's there currently, instead of creating a brand new layout. if (layoutName == matchedLayout) { return(layoutName); } var layout = new XRLayoutBuilder { descriptor = deviceDescriptor, parentLayout = matchedLayout, interfaceName = description.interfaceName }; InputSystem.RegisterLayoutBuilder(() => layout.Build(), layoutName, matchedLayout, InputDeviceMatcher.FromDeviceDescription(description)); return(layoutName); }
// This is the workhorse for figuring out fallback options for HIDs attached to the system. // If the system cannot find a more specific layout for a given HID, this method will try // to produce a layout builder on the fly based on the HID descriptor received from // the device. internal static unsafe string OnFindControlLayoutForDevice(int deviceId, ref InputDeviceDescription description, string matchedLayout, IInputRuntime runtime) { // If the system found a matching layout, there's nothing for us to do. if (!string.IsNullOrEmpty(matchedLayout)) { return(null); } // If the device isn't a HID, we're not interested. if (description.interfaceName != kHIDInterface) { return(null); } // See if we have to request a HID descriptor from the device. // We support having the descriptor directly as a JSON string in the `capabilities` // field of the device description. var needToRequestDescriptor = true; var hidDeviceDescriptor = new HIDDeviceDescriptor(); if (!string.IsNullOrEmpty(description.capabilities)) { try { hidDeviceDescriptor = HIDDeviceDescriptor.FromJson(description.capabilities); // If there's elements in the descriptor, we're good with the descriptor. If there aren't, // we go and ask the device for a full descriptor. if (hidDeviceDescriptor.elements != null && hidDeviceDescriptor.elements.Length > 0) { needToRequestDescriptor = false; } } catch (Exception exception) { Debug.Log(string.Format("Could not parse HID descriptor (exception: {0})", exception)); } } ////REVIEW: we *could* switch to a single path here that supports *only* parsed descriptors but it'd //// mean having to switch *every* platform supporting HID to the hack we currently have to do //// on Windows // Request descriptor, if necessary. if (needToRequestDescriptor) { // If the device has no assigned ID yet, we can't perform IOCTLs on the // device so no way to get a report descriptor. if (deviceId == kInvalidDeviceId) { return(null); } // Try to get the size of the HID descriptor from the device. var sizeOfDescriptorCommand = new InputDeviceCommand(QueryHIDReportDescriptorSizeDeviceCommandType); var sizeOfDescriptorInBytes = runtime.DeviceCommand(deviceId, ref sizeOfDescriptorCommand); if (sizeOfDescriptorInBytes > 0) { // Now try to fetch the HID descriptor. using (var buffer = InputDeviceCommand.AllocateNative(QueryHIDReportDescriptorDeviceCommandType, (int)sizeOfDescriptorInBytes)) { var commandPtr = (InputDeviceCommand *)NativeArrayUnsafeUtility.GetUnsafePtr(buffer); if (runtime.DeviceCommand(deviceId, ref *commandPtr) != sizeOfDescriptorInBytes) { return(null); } // Try to parse the HID report descriptor. if (!HIDParser.ParseReportDescriptor((byte *)commandPtr->payloadPtr, (int)sizeOfDescriptorInBytes, ref hidDeviceDescriptor)) { return(null); } } // Update the descriptor on the device with the information we got. description.capabilities = hidDeviceDescriptor.ToJson(); } else { // The device may not support binary descriptors but may support parsed descriptors so // try the IOCTL for parsed descriptors next. // // This path exists pretty much only for the sake of Windows where it is not possible to get // unparsed/binary descriptors from the device (and where getting element offsets is only possible // with some dirty hacks we're performing in the native runtime). const int kMaxDescriptorBufferSize = 2 * 1024 * 1024; ////TODO: switch to larger buffer based on return code if request fails using (var buffer = InputDeviceCommand.AllocateNative(QueryHIDParsedReportDescriptorDeviceCommandType, kMaxDescriptorBufferSize)) { var commandPtr = (InputDeviceCommand *)NativeArrayUnsafeUtility.GetUnsafePtr(buffer); var utf8Length = runtime.DeviceCommand(deviceId, ref *commandPtr); if (utf8Length < 0) { return(null); } // Turn UTF-8 buffer into string. ////TODO: is there a way to not have to copy here? var utf8 = new byte[utf8Length]; fixed(byte *utf8Ptr = utf8) { UnsafeUtility.MemCpy(utf8Ptr, commandPtr->payloadPtr, utf8Length); } var descriptorJson = Encoding.UTF8.GetString(utf8, 0, (int)utf8Length); // Try to parse the HID report descriptor. try { hidDeviceDescriptor = HIDDeviceDescriptor.FromJson(descriptorJson); } catch (Exception exception) { Debug.Log(string.Format("Could not parse HID descriptor JSON returned from runtime (exception: {0})", exception)); return(null); } // Update the descriptor on the device with the information we got. description.capabilities = descriptorJson; } } } // Determine if there's any usable elements on the device. var hasUsableElements = false; if (hidDeviceDescriptor.elements != null) { foreach (var element in hidDeviceDescriptor.elements) { if (element.DetermineLayout() != null) { hasUsableElements = true; break; } } } // If not, there's nothing we can do with the device. if (!hasUsableElements) { return(null); } // Determine base layout. var baseLayout = "HID"; if (hidDeviceDescriptor.usagePage == UsagePage.GenericDesktop) { /* * ////TODO: there's some work to be done to make the HID *actually* compatible with these devices * if (hidDeviceDescriptor.usage == (int)GenericDesktop.Joystick) * baseLayout = "Joystick"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Gamepad) * baseLayout = "Gamepad"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Mouse) * baseLayout = "Mouse"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Pointer) * baseLayout = "Pointer"; * else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Keyboard) * baseLayout = "Keyboard"; */ } ////TODO: match HID layouts by vendor and product ID ////REVIEW: this probably works fine for most products out there but I'm not sure it works reliably for all cases // Come up with a unique template name. HIDs are required to have product and vendor IDs. // We go with the string versions if we have them and with the numeric versions if we don't. string layoutName; if (!string.IsNullOrEmpty(description.product) && !string.IsNullOrEmpty(description.manufacturer)) { layoutName = string.Format("{0}::{1} {2}", kHIDNamespace, description.manufacturer, description.product); } else { // Sanity check to make sure we really have the data we expect. if (hidDeviceDescriptor.vendorId == 0) { return(null); } layoutName = string.Format("{0}::{1:X}-{2:X}", kHIDNamespace, hidDeviceDescriptor.vendorId, hidDeviceDescriptor.productId); } // Register layout builder that will turn the HID descriptor into an // InputControlLayout instance. var layout = new HIDLayoutBuilder { hidDescriptor = hidDeviceDescriptor }; InputSystem.RegisterControlLayoutBuilder(() => layout.Build(), layoutName, baseLayout, InputDeviceMatcher.FromDeviceDescription(description)); return(layoutName); }