Exemple #1
0
        public void RegisterDefaultInterfaces()
        {
            foreach (var usbInterface in UsbInterfaces)
            {
                usbInterface.RegisterDefaultEndpoints();
            }

            ReadUsbInterface           = UsbInterfaces.FirstOrDefault(i => i.ReadEndpoint != null);
            WriteUsbInterface          = UsbInterfaces.FirstOrDefault(i => i.WriteEndpoint != null);
            ReadInterruptUsbInterface  = UsbInterfaces.FirstOrDefault(i => i.InterruptReadEndpoint != null);
            WriteInterruptUsbInterface = UsbInterfaces.FirstOrDefault(i => i.InterruptWriteEndpoint != null);
        }
Exemple #2
0
        public void Close()
        {
            foreach (var usbInterface in UsbInterfaces)
            {
                usbInterface.Dispose();
            }

            UsbInterfaces.Clear();

            _DeviceHandle?.Dispose();
            _DeviceHandle = null;
        }
        public void RegisterDefaultInterfaces()
        {
            foreach (var usbInterface in UsbInterfaces)
            {
                usbInterface.RegisterDefaultEndpoints();
            }

            ReadUsbInterface           = UsbInterfaces.FirstOrDefault(i => i.ReadEndpoint != null);
            WriteUsbInterface          = UsbInterfaces.FirstOrDefault(i => i.WriteEndpoint != null);
            ReadInterruptUsbInterface  = UsbInterfaces.FirstOrDefault(i => i.InterruptReadEndpoint != null);
            WriteInterruptUsbInterface = UsbInterfaces.FirstOrDefault(i => i.InterruptWriteEndpoint != null);

            Logger.LogInformation("Defaults: Read interface: {readInterface} Write interface {writeInterface} Read PipeId: {readPipeId} Write PipeId: {writePipeId}",
                                  ReadUsbInterface?.InterfaceNumber,
                                  WriteUsbInterface?.InterfaceNumber,
                                  ReadUsbInterface?.ReadEndpoint?.PipeId,
                                  WriteUsbInterface?.WriteEndpoint?.PipeId
                                  );
        }
        private void Initialize()
        {
            using var logScope = Logger.BeginScope("DeviceId: {deviceId} Call: {call}", DeviceId, nameof(Initialize));

            try
            {
                Close();

                int errorCode;

                if (string.IsNullOrEmpty(DeviceId))
                {
                    throw new ValidationException(
                              $"{nameof(ConnectedDeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
                }

                _DeviceHandle = APICalls.CreateFile(DeviceId,
                                                    FileAccessRights.GenericWrite | FileAccessRights.GenericRead,
                                                    APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting,
                                                    APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);

                if (_DeviceHandle.IsInvalid)
                {
                    //TODO: is error code useful here?
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode > 0)
                    {
                        throw new ApiException($"Device handle no good. Error code: {errorCode}");
                    }
                }

                Logger.LogInformation(Messages.SuccessMessageGotWriteAndReadHandle);

                var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var interfaceHandle);
                _ = WindowsHelpers.HandleError(isSuccess, Messages.ErrorMessageCouldntIntializeDevice, Logger);

#pragma warning disable CA2000 //We need to hold on to this handle
                var defaultInterfaceHandle = new SafeFileHandle(interfaceHandle, false);
#pragma warning restore CA2000
                var connectedDeviceDefinition = GetDeviceDefinition(defaultInterfaceHandle, DeviceId, Logger);

                if (!WriteBufferSizeProtected.HasValue)
                {
                    if (!connectedDeviceDefinition.WriteBufferSize.HasValue)
                    {
                        throw new ValidationException("Write buffer size not specified");
                    }
                    WriteBufferSizeProtected = (ushort)connectedDeviceDefinition.WriteBufferSize.Value;
                }

                if (!ReadBufferSizeProtected.HasValue)
                {
                    if (!connectedDeviceDefinition.ReadBufferSize.HasValue)
                    {
                        throw new ValidationException("Read buffer size not specified");
                    }
                    ReadBufferSizeProtected = (ushort)connectedDeviceDefinition.ReadBufferSize.Value;
                }

                //Get the first (default) interface
#pragma warning disable CA2000 //Ths should be disposed later
                var defaultInterface = GetInterface(defaultInterfaceHandle);

                UsbInterfaces.Add(defaultInterface);

                byte i = 0;
                while (true)
                {
                    isSuccess = WinUsbApiCalls.WinUsb_GetAssociatedInterface(defaultInterfaceHandle, i,
                                                                             out var interfacePointer);
                    if (!isSuccess)
                    {
                        errorCode = Marshal.GetLastWin32Error();
                        if (errorCode == APICalls.ERROR_NO_MORE_ITEMS)
                        {
                            break;
                        }

                        throw new ApiException(
                                  $"Could not enumerate interfaces for device. Error code: {errorCode}");
                    }

                    var associatedInterface = GetInterface(interfacePointer);

                    //TODO: this is bad design. The handler should be taking care of this
                    UsbInterfaces.Add(associatedInterface);

                    i++;
                }

                RegisterDefaultInterfaces();
#pragma warning restore CA2000
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, Messages.ErrorMessageCouldntIntializeDevice);
                throw;
            }
        }
        public async Task InitializeAsync()
        {
            try
            {
                if (disposed)
                {
                    throw new Exception(Messages.DeviceDisposedErrorMessage);
                }

                await _InitializingSemaphoreSlim.WaitAsync();

                Close();

                _UsbDevice = UsbManager.DeviceList.Select(d => d.Value).FirstOrDefault(d => d.DeviceId == DeviceNumberId);
                if (_UsbDevice == null)
                {
                    throw new Exception($"The device {DeviceNumberId} is not connected to the system");
                }
                Logger?.Log($"Found device: {_UsbDevice.DeviceName} Id: {_UsbDevice.DeviceId}", nameof(AndroidUsbInterfaceManager), null, LogLevel.Information);


                var isPermissionGranted = await RequestPermissionAsync();

                if (!isPermissionGranted.HasValue)
                {
                    throw new Exception("User did not respond to permission request");
                }

                if (!isPermissionGranted.Value)
                {
                    throw new Exception("The user did not give the permission to access the device");
                }

                _UsbDeviceConnection = UsbManager.OpenDevice(_UsbDevice);

                if (_UsbDeviceConnection == null)
                {
                    throw new Exception("could not open connection");
                }

                for (var x = 0; x < _UsbDevice.InterfaceCount; x++)
                {
                    //TODO: This is the default interface but other interfaces might be needed so this needs to be changed.
                    var usbInterface = _UsbDevice.GetInterface(x);

                    var androidUsbInterface = new AndroidUsbInterface(usbInterface, _UsbDeviceConnection, Logger, Tracer, _ReadBufferSize, _WriteBufferSize);
                    UsbInterfaces.Add(androidUsbInterface);

                    for (var y = 0; y < usbInterface.EndpointCount; y++)
                    {
                        var usbEndpoint = usbInterface.GetEndpoint(y);

                        if (usbEndpoint != null)
                        {
                            //TODO: This is probably all wrong...
                            var androidUsbEndpoint = new AndroidUsbEndpoint(usbEndpoint);
                            androidUsbInterface.UsbInterfaceEndpoints.Add(androidUsbEndpoint);
                        }
                    }
                }

                Log("Hid device initialized. About to tell everyone.", null);

                RegisterDefaultInterfaces();
            }
            catch (Exception ex)
            {
                Log("Error initializing Hid Device", ex);
                throw;
            }
            finally
            {
                _InitializingSemaphoreSlim.Release();
            }
        }
Exemple #6
0
        private void Initialize()
        {
            try
            {
                Close();

                int errorCode;

                if (string.IsNullOrEmpty(DeviceId))
                {
                    throw new ValidationException($"{nameof(DeviceDefinitionBase)} must be specified before {nameof(InitializeAsync)} can be called.");
                }

                _DeviceHandle = APICalls.CreateFile(DeviceId, FileAccessRights.GenericWrite | FileAccessRights.GenericRead, APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);

                if (_DeviceHandle.IsInvalid)
                {
                    //TODO: is error code useful here?
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode > 0)
                    {
                        throw new ApiException($"Device handle no good. Error code: {errorCode}");
                    }
                }

                Logger?.Log(Messages.SuccessMessageGotWriteAndReadHandle, nameof(WindowsUsbInterfaceManager), null, LogLevel.Information);

                var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var defaultInterfaceHandle);
                WindowsDeviceBase.HandleError(isSuccess, Messages.ErrorMessageCouldntIntializeDevice);

                var connectedDeviceDefinition = WindowsUsbDeviceFactory.GetDeviceDefinition(defaultInterfaceHandle, DeviceId);

                if (!_WriteBufferSize.HasValue)
                {
                    if (!connectedDeviceDefinition.WriteBufferSize.HasValue)
                    {
                        throw new ValidationException("Write buffer size not specified");
                    }
                    _WriteBufferSize = (ushort)connectedDeviceDefinition.WriteBufferSize.Value;
                }

                if (!_ReadBufferSize.HasValue)
                {
                    if (!connectedDeviceDefinition.ReadBufferSize.HasValue)
                    {
                        throw new ValidationException("Read buffer size not specified");
                    }
                    _ReadBufferSize = (ushort)connectedDeviceDefinition.ReadBufferSize.Value;
                }

                //Get the first (default) interface
                var defaultInterface = GetInterface(defaultInterfaceHandle);

                UsbInterfaces.Add(defaultInterface);

                byte i = 0;
                while (true)
                {
                    isSuccess = WinUsbApiCalls.WinUsb_GetAssociatedInterface(defaultInterfaceHandle, i, out var interfacePointer);
                    if (!isSuccess)
                    {
                        errorCode = Marshal.GetLastWin32Error();
                        if (errorCode == APICalls.ERROR_NO_MORE_ITEMS)
                        {
                            break;
                        }

                        throw new ApiException($"Could not enumerate interfaces for device. Error code: { errorCode}");
                    }

                    var associatedInterface = GetInterface(interfacePointer);

                    //TODO: this is bad design. The handler should be taking care of this
                    UsbInterfaces.Add(associatedInterface);

                    i++;
                }

                RegisterDefaultInterfaces();
            }
            catch (Exception ex)
            {
                Logger?.Log($"{nameof(Initialize)} error. DeviceId {DeviceId}", nameof(UsbDevice), ex, LogLevel.Error);
                throw;
            }
        }
Exemple #7
0
        public async Task InitializeAsync(CancellationToken cancellationToken = default)
        {
            if (disposed)
            {
                throw new DeviceException(Messages.DeviceDisposedErrorMessage);
            }

            using var logScope = Logger.BeginScope("DeviceId: {deviceId} Call: {call}", DeviceNumberId, nameof(InitializeAsync));

            if (IsInitialized)
            {
                Logger.LogWarning("Device is already initialized...");
            }

            Logger.LogInformation("Attempting to initialize...");

            try
            {
                await Task.Run(async() =>
                {
                    Logger.LogTrace("Waiting for initialization lock ... {deviceId}", DeviceNumberId);

                    await _InitializingSemaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false);

                    Close();

                    _UsbDevice = UsbManager.DeviceList.Select(d => d.Value).FirstOrDefault(d => d.DeviceId == DeviceNumberId);

                    if (_UsbDevice == null)
                    {
                        throw new DeviceException($"The device {DeviceNumberId} is not connected to the system");
                    }

                    Logger.LogInformation("Found device: {deviceName} Id: {deviceId}", _UsbDevice.DeviceName, _UsbDevice.DeviceId);

                    var isPermissionGranted = await RequestPermissionAsync().ConfigureAwait(false);
                    if (!isPermissionGranted.HasValue)
                    {
                        throw new DeviceException("User did not respond to permission request");
                    }

                    if (!isPermissionGranted.Value)
                    {
                        throw new DeviceException("The user did not give the permission to access the device");
                    }

                    _UsbDeviceConnection = UsbManager.OpenDevice(_UsbDevice);

                    if (_UsbDeviceConnection == null)
                    {
                        throw new DeviceException("could not open connection");
                    }

                    Logger.LogInformation("Interface count: {count}", _UsbDevice.InterfaceCount);

                    for (var interfaceNumber = 0; interfaceNumber < _UsbDevice.InterfaceCount; interfaceNumber++)
                    {
                        //TODO: This is the default interface but other interfaces might be needed so this needs to be changed.
                        var usbInterface = _UsbDevice.GetInterface(interfaceNumber);

                        var androidUsbInterface = new AndroidUsbInterface(
                            usbInterface,
                            _UsbDeviceConnection,
                            _androidFactory,
                            LoggerFactory.CreateLogger <AndroidUsbInterface>(),
                            ReadBufferSizeProtected,
                            WriteBufferSizeProtected);

                        Logger.LogInformation("Interface found. Id: {id} Endpoint Count: {endpointCount} Interface Class: {interfaceclass} Interface Subclass: {interfacesubclass} Name: {name}", usbInterface.Id, usbInterface.EndpointCount, usbInterface.InterfaceClass, usbInterface.InterfaceSubclass, usbInterface.Name);

                        UsbInterfaces.Add(androidUsbInterface);

                        for (var endpointNumber = 0; endpointNumber < usbInterface.EndpointCount; endpointNumber++)
                        {
                            var usbEndpoint = usbInterface.GetEndpoint(endpointNumber);

                            if (usbEndpoint == null)
                            {
                                continue;
                            }
                            var androidUsbEndpoint = new AndroidUsbEndpoint(usbEndpoint, interfaceNumber, LoggerFactory.CreateLogger <AndroidUsbEndpoint>());
                            androidUsbInterface.UsbInterfaceEndpoints.Add(androidUsbEndpoint);
                        }

                        await androidUsbInterface.ClaimInterface().ConfigureAwait(false);
                    }

                    RegisterDefaultInterfaces();

                    Logger.LogInformation("Device initialized successfully.");
                }, cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Error initializing device");
                throw;
            }
            finally
            {
                Logger.LogTrace("Releasing initialization lock");
                _ = _InitializingSemaphoreSlim.Release();
            }
        }
        public async Task InitializeAsync(CancellationToken cancellationToken = default)
        {
            if (disposed)
            {
                throw new ValidationException(Messages.DeviceDisposedErrorMessage);
            }

            await Task.Run(() =>
            {
                //TODO: Error handling etc.
                _ = UsbDevice.Open();

                switch (UsbDevice)
                {
                //TODO: This is far beyond not cool.
                case MonoUsbDevice monoUsbDevice:
                    _ = monoUsbDevice.ClaimInterface(0);
                    break;

                case WinUsbDevice winUsbDevice:
                    //Doesn't seem necessary in this case...
                    break;

                default:
                    _ = ((IUsbDevice)UsbDevice).ClaimInterface(0);
                    break;
                }

                foreach (var usbConfigInfo in UsbDevice.Configs)
                {
                    foreach (var usbInterfaceInfo in usbConfigInfo.InterfaceInfoList)
                    {
                        //Create an interface.
                        var usbInterface = new UsbInterface(UsbDevice, usbInterfaceInfo.Descriptor.InterfaceID, null, null, Logger, Timeout);

                        UsbInterfaces.Add(usbInterface);

                        ReadUsbInterface ??= usbInterface;
                        WriteUsbInterface ??= usbInterface;

                        //Write endpoint
                        var usbEndpointWriter = UsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
                        var writeBufferSize   = _writeBufferSize ?? 64;
                        var writeEndpoint     = new WriteEndpoint(usbEndpointWriter, writeBufferSize);
                        usbInterface.UsbInterfaceEndpoints.Add(writeEndpoint);
                        usbInterface.WriteEndpoint ??= writeEndpoint;

                        //Read endpoint
                        var usbEndpointReader = UsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);
                        var readBufferSize    = _readBufferSize ?? 64;
                        var readEndpoint      = new ReadEndpoint(usbEndpointReader, readBufferSize);
                        usbInterface.UsbInterfaceEndpoints.Add(readEndpoint);
                        usbInterface.ReadEndpoint ??= readEndpoint;

                        //int endpointCount = usbInterfaceInfo.EndpointInfoList.Count;

                        /*
                         * for (var i = 0; i < endpointCount; i++)
                         * {
                         *  var usbEndpointInfo = usbInterfaceInfo.EndpointInfoList[i];
                         *
                         *  //var IsWrite = (usbEndpointInfo.Descriptor.EndpointID & 128) == 0;
                         *  //var IsRead = (usbEndpointInfo.Descriptor.EndpointID & 128) != 0;
                         *
                         *  //Write endpoint
                         *  //var id = usbEndpointInfo.Descriptor.EndpointID ^ 128;
                         *  //var writeEndpointID = (WriteEndpointID)Enum.Parse(typeof(WriteEndpointID), $"Ep{id.ToString().PadLeft(2, '0')}");
                         *  var usbEndpointWriter = UsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
                         *  var writeBufferSize = _WriteBufferSize ?? (ushort)usbEndpointInfo.Descriptor.MaxPacketSize;
                         *  var writeEndpoint = new WriteEndpoint(usbEndpointWriter, writeBufferSize);
                         *  usbInterface.UsbInterfaceEndpoints.Add(writeEndpoint);
                         *  if (usbInterface.WriteEndpoint == null) usbInterface.WriteEndpoint = writeEndpoint;
                         *
                         *  //Read endpoint
                         *  //var id = usbEndpointInfo.Descriptor.EndpointID ^ 1;
                         *  //var readEndpointID = (ReadEndpointID)Enum.Parse(typeof(ReadEndpointID), $"Ep{id.ToString().PadLeft(2, '0')}");
                         *  var usbEndpointReader = UsbDevice.OpenEndpointReader(ReadEndpointID.Ep01);
                         *  var readBufferSize = _ReadBufferSize ?? (ushort)usbEndpointInfo.Descriptor.MaxPacketSize;
                         *  var readEndpoint = new ReadEndpoint(usbEndpointReader, readBufferSize);
                         *  usbInterface.UsbInterfaceEndpoints.Add(readEndpoint);
                         *  if (usbInterface.ReadEndpoint == null) usbInterface.ReadEndpoint = readEndpoint;
                         * }
                         */
                    }

                    ReadUsbInterface  = UsbInterfaces[0];
                    WriteUsbInterface = UsbInterfaces[0];
                }

                IsInitialized = true;
            }, cancellationToken).ConfigureAwait(false);
        }