コード例 #1
0
        // 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();
            }
        }
コード例 #2
0
        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);
        }