// why does this have to be async? private async void DeviceAdded(DeviceWatcherCallbackReference callbackRef, IntPtr iterator) { var it = new IOIterator(iterator); var usbDevice = it.Next(); while (usbDevice != null) { var vendorString = usbDevice.GetCFPropertyString(IOKitFramework.kUSBVendorString); var productString = usbDevice.GetCFPropertyString(IOKitFramework.kUSBProductString); var serialNumber = usbDevice.GetCFPropertyString(IOKitFramework.kUSBSerialNumberString); Debug.WriteLine("Found Device:"); Debug.WriteLine("Vendor: " + vendorString); Debug.WriteLine("Product: " + productString); Debug.WriteLine("Serial Number: " + serialNumber); Debug.WriteLine(""); var idx = OnDeviceAdded(usbDevice, productString, serialNumber); var ptr = GCHandle.ToIntPtr(GCHandle.Alloc(this.OnDeviceRemoved, GCHandleType.Pinned)); var removedCallback = new DeviceWatcherCallbackReference() { deviceIndex = idx, removedCallback = ptr }; GCHandle.Alloc(removedCallback, GCHandleType.Pinned); GCHandle.Alloc(this, GCHandleType.Pinned); GCHandle.Alloc(this.OnDeviceRemoved, GCHandleType.Pinned); var kr = NativeMethods.IOServiceAddInterestNotification( gNotifyPort, // notifyPort usbDevice.Handle, // service IOKitFramework.kIOGeneralInterest, // interestType DeviceRemoved, // callback removedCallback, // refCon ref notificationPtr // notification ); usbDevice = it.Next(); } }
public async Task <bool> OpenAsync() { deviceInterface.GetDeviceAsyncEventSource(deviceInterface.Handle); var kr = deviceInterface.USBDeviceOpen(deviceInterface.Handle); if (kr != IOKitError.Success) { Debug.WriteLine("Couldn’t open device: " + kr); return(false); } byte numConfigs = 0; deviceInterface.GetNumberOfConfigurations(deviceInterface.Handle, out numConfigs); if (numConfigs == 0) { return(false); } IOUSBConfigurationDescriptor configDesc = new IOUSBConfigurationDescriptor(); kr = deviceInterface.GetConfigurationDescriptorPtr(deviceInterface.Handle, 0, out configDesc); if (kr != IOKitError.Success) { Debug.WriteLine("Couldn’t get configuration descriptor for index: " + kr); return(false); } kr = deviceInterface.SetConfiguration(deviceInterface.Handle, configDesc.bConfigurationValue); if (kr != IOKitError.Success) { Debug.WriteLine("Couldn’t set configuration to value: " + kr); return(false); } // HACK: the LED blinks three times since we reconfigured it. Ugh, we should wait here so we don't miss commands await Task.Delay(500).ConfigureAwait(false); IOUSBFindInterfaceRequest interfaceRequest = new IOUSBFindInterfaceRequest(); IntPtr interfaceIteratorPtr = IntPtr.Zero; kr = deviceInterface.CreateInterfaceIterator(deviceInterface.Handle, interfaceRequest, out interfaceIteratorPtr); if (kr != IOKitError.Success) { Debug.WriteLine("Failed to create interface iterator: " + kr); return(false); } IOIterator interfaceIterator = new IOIterator(interfaceIteratorPtr); var usbInterface = interfaceIterator.Next(); if (usbInterface == null) { Debug.WriteLine("Failed to find an interface."); return(false); } IntPtr pluginInterfacePtrPtr = IntPtr.Zero; int score = 0; if (NativeMethods.IOCreatePlugInInterfaceForService(usbInterface.Handle, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, out pluginInterfacePtrPtr, out score) != IOKitError.Success) { Debug.WriteLine("Failed to create CF Plug-In interface: " + kr); return(false); } IOCFPlugInInterface pluginInterface = IOCFPlugInInterface.GetPlugInInterfaceFromPtrPtr(pluginInterfacePtrPtr); usbInterface.Dispose(); interfaceIterator.Dispose(); IntPtr interfaceInterfacePtrPtr = IntPtr.Zero; if (pluginInterface.QueryInterface(pluginInterfacePtrPtr, kIOUSBInterfaceInterfaceID, out interfaceInterfacePtrPtr) != IOKitError.Success) { Debug.WriteLine("Could not query plugin interface to retrieve interface interface: " + kr); return(false); } IntPtr interfaceInterfacePtr = new IntPtr(Marshal.ReadInt64(interfaceInterfacePtrPtr)); if (interfaceInterfacePtr == IntPtr.Zero) { Debug.WriteLine("Bad InterfaceInterface pointer"); return(false); } interfaceInterface = (IOUSBInterfaceInterface197)Marshal.PtrToStructure(interfaceInterfacePtr, typeof(IOUSBInterfaceInterface197)); interfaceInterface.Handle = interfaceInterfacePtrPtr; byte intNumber = 0; interfaceInterface.GetNumEndpoints(interfaceInterface.Handle, out intNumber); interfaceInterface.GetInterfaceClass(interfaceInterface.Handle, out intNumber); kr = interfaceInterface.GetInterfaceNumber(interfaceInterface.Handle, out intNumber); if (kr != IOKitError.Success) { Debug.WriteLine("Couldn't get interface number: " + kr); return(false); } kr = interfaceInterface.USBInterfaceOpen(interfaceInterface.Handle); if (kr != IOKitError.Success) { Debug.WriteLine("Couldn't open interface: " + kr); return(false); } isConnected = true; pinReportThread = new Thread(() => { byte[] pinReport = new byte[41]; uint numBytesToRead = 41; while (isConnected) { var status = interfaceInterface.ReadPipeTO(interfaceInterface.Handle, 1, pinReport, out numBytesToRead, 1000, 1000); switch (status) { case IOKitError.Success: PinEventDataReceived?.Invoke(pinReport); break; case IOKitError.NoDevice: case IOKitError.Aborted: return; // board was unplugged, so kill this thread break; case IOKitError.TransactionTimedOut: // we probably don't have any inputs activated. No need to report to the user. status = interfaceInterface.ClearPipeStallBothEnds(interfaceInterface.Handle, 1); break; default: Debug.WriteLine("Read from pin report failed: " + status); status = interfaceInterface.ClearPipeStallBothEnds(interfaceInterface.Handle, 1); if (status != IOKitError.Success) { Debug.WriteLine("Can't clear pipe stall: " + status); } break; } Thread.Sleep(UpdateRate); } }); pinReportThread.Name = "PinReportThread"; pinReportThread.Start(); return(true); }