Example #1
0
 private void pinStateCallback(IAsyncResult result)
 {
     EndRead(result);
     PinEventDataReceived?.Invoke(pinReportBuffer);
     if (!IsOpen)
     {
         return;
     }
     try
     {
         BeginRead(pinReportEndpoint, pinReportBuffer, pinReportBuffer.Length, pinStateCallback,
                   null); // start another read
     }
     catch (Exception ex)
     {
         Debug.WriteLine("Exception: " + ex.Message);
     }
 }
        public async Task <bool> OpenAsync()
        {
            var handle = new IntPtr();

            NativeMethods.Open(deviceProfile, ref handle);
            deviceHandle = new LibUsbDeviceHandle(handle);
            NativeMethods.ClaimInterface(deviceHandle, 0);

            isOpen = true;

            pinListenerTask = new Task(async() =>
            {
                while (isOpen)
                {
                    var buffer = new byte[41];
                    var len    = 0;
                    try
                    {
                        var res = NativeMethods.BulkTransfer(deviceHandle, pinReportEndpoint, buffer, buffer.Length,
                                                             out len, 1000);

                        switch (res)
                        {
                        case LibUsbError.Success:
                            PinEventDataReceived?.Invoke(buffer);
                            break;

                        case LibUsbError.ErrorNoDevice:
                        case LibUsbError.ErrorPipe:
                        case LibUsbError.ErrorOverflow:
                            this.Close();
                            // HACK ALERT: device removal notifications don't seem to work right, so if we get ErrorNoDevice,
                            // request that ConnectionService remove the board that matches our device path.
                            ((LibUsbConnectionService)ConnectionService.Instance).RemoveDevice(this.DevicePath);
                            break;

                        case LibUsbError.ErrorTimeout:
                        case LibUsbError.ErrorIO:
                            break;     // normal behavior

                        default:
                            Debug.WriteLine("Pin Data Read Failure: " + res);
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Exception: " + ex.Message);
                    }

                    int rate = (int)Math.Round(1000.0 / UpdateRate);

                    if (rate > 1)
                    {
                        await Task.Delay(rate).ConfigureAwait(false);
                    }
                }
            });

            pinListenerTask.Start();

            return(true);
        }
        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);
        }