private WindowsUsbInterface GetInterface(SafeFileHandle interfaceHandle)
        {
            //TODO: We need to get the read/write size from a different API call...

            //TODO: Where is the logger/tracer?
            var isSuccess = WinUsbApiCalls.WinUsb_QueryInterfaceSettings(interfaceHandle, 0, out var interfaceDescriptor);

            var retVal = new WindowsUsbInterface(interfaceHandle, interfaceDescriptor.bInterfaceNumber, Logger, ReadBufferSizeProtected, WriteBufferSizeProtected);

            _ = WindowsHelpers.HandleError(isSuccess, "Couldn't query interface", Logger);

            Logger.LogInformation(
                "Found Interface Number: {interfaceNumber} Endpoint count: {endpointCount} Class: {class} Subclass: {subClass}",
                interfaceDescriptor.bInterfaceNumber,
                interfaceDescriptor.bNumEndpoints,
                interfaceDescriptor.bInterfaceClass,
                interfaceDescriptor.bInterfaceSubClass);

            for (byte i = 0; i < interfaceDescriptor.bNumEndpoints; i++)
            {
                isSuccess = WinUsbApiCalls.WinUsb_QueryPipe(interfaceHandle, 0, i, out var pipeInfo);
                _         = WindowsHelpers.HandleError(isSuccess, "Couldn't query endpoint", Logger);

                Logger.LogInformation("Found PipeId: {pipeId} PipeType: {pipeType} MaxPacketSize: {maxPacketSize}", pipeInfo.PipeId, pipeInfo.PipeType, pipeInfo.MaximumPacketSize);

                //TODO: We are dropping the max packet size here...

                retVal.UsbInterfaceEndpoints.Add(new WindowsUsbInterfaceEndpoint(pipeInfo.PipeId, pipeInfo.PipeType, pipeInfo.MaximumPacketSize));
            }

            return(retVal);
        }
Ejemplo n.º 2
0
        private static ConnectedDeviceDefinition GetDeviceDefinition(SafeFileHandle defaultInterfaceHandle, string deviceId)
        {
            var deviceDefinition = new ConnectedDeviceDefinition(deviceId)
            {
                DeviceType = DeviceType.Usb
            };

            var bufferLength = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));
            var isSuccess2   = WinUsbApiCalls.WinUsb_GetDescriptor(defaultInterfaceHandle, WinUsbApiCalls.DEFAULT_DESCRIPTOR_TYPE, 0, WinUsbApiCalls.EnglishLanguageID, out var _UsbDeviceDescriptor, bufferLength, out var lengthTransferred);

            HandleError(isSuccess2, "Couldn't get device descriptor");

            if (_UsbDeviceDescriptor.iProduct > 0)
            {
                deviceDefinition.ProductName = WinUsbApiCalls.GetDescriptor(defaultInterfaceHandle, _UsbDeviceDescriptor.iProduct, "Couldn't get product name");
            }

            if (_UsbDeviceDescriptor.iSerialNumber > 0)
            {
                deviceDefinition.SerialNumber = WinUsbApiCalls.GetDescriptor(defaultInterfaceHandle, _UsbDeviceDescriptor.iSerialNumber, "Couldn't get serial number");
            }

            if (_UsbDeviceDescriptor.iManufacturer > 0)
            {
                deviceDefinition.Manufacturer = WinUsbApiCalls.GetDescriptor(defaultInterfaceHandle, _UsbDeviceDescriptor.iManufacturer, "Couldn't get manufacturer");
            }

            deviceDefinition.VendorId        = _UsbDeviceDescriptor.idVendor;
            deviceDefinition.ProductId       = _UsbDeviceDescriptor.idProduct;
            deviceDefinition.WriteBufferSize = _UsbDeviceDescriptor.bMaxPacketSize0;
            deviceDefinition.ReadBufferSize  = _UsbDeviceDescriptor.bMaxPacketSize0;

            return(deviceDefinition);
        }
Ejemplo n.º 3
0
        //TODO: make async?
        //TODO: WINUSB_SETUP_PACKET not exposed
        public uint ControlTransfer(WINUSB_SETUP_PACKET setupPacket, byte[] buffer)
        {
            uint bytesWritten = 0;

            //TODO: cannot convert from SafeFileHandle to IntPtr
            WinUsbApiCalls.WinUsb_ControlTransfer(_SafeFileHandle, setupPacket, buffer, (uint)buffer.Length, ref bytesWritten, IntPtr.Zero);      //last pointer is overlapped structure for async operations
            return(bytesWritten);
        }
Ejemplo n.º 4
0
        private void Initialize()
        {
            Dispose();

            int errorCode;

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

            _DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.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 Exception($"Device handle no good. Error code: {errorCode}");
                }
            }

            var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var defaultInterfaceHandle);

            HandleError(isSuccess, "Couldn't initialize device");

            ConnectedDeviceDefinition = GetDeviceDefinition(defaultInterfaceHandle, DeviceId);

            byte i = 0;

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

            _UsbInterfaces.Add(defaultInterface);

            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 Exception($"Could not enumerate interfaces for device {DeviceId}. Error code: { errorCode}");
                }

                var associatedInterface = GetInterface(interfacePointer);

                _UsbInterfaces.Add(associatedInterface);

                i++;
            }
        }
Ejemplo n.º 5
0
 public async Task WriteAsync(byte[] data)
 {
     await Task.Run(() =>
     {
         var isSuccess = WinUsbApiCalls.WinUsb_WritePipe(_SafeFileHandle, WriteEndpoint.PipeId, data, (uint)data.Length, out var bytesWritten, IntPtr.Zero);
         WindowsDeviceBase.HandleError(isSuccess, "Couldn't write data");
         Tracer?.Trace(true, data);
     });
 }
Ejemplo n.º 6
0
 public async Task <ReadResult> ReadAsync(uint bufferLength)
 {
     return(await Task.Run(() =>
     {
         var bytes = new byte[bufferLength];
         var isSuccess = WinUsbApiCalls.WinUsb_ReadPipe(_SafeFileHandle, ReadEndpoint.PipeId, bytes, bufferLength, out var bytesRead, IntPtr.Zero);
         WindowsDeviceBase.HandleError(isSuccess, "Couldn't read data");
         Tracer?.Trace(false, bytes);
         return new ReadResult(bytes, bytesRead);
     }));
 }
Ejemplo n.º 7
0
 public override async Task <byte[]> ReadAsync()
 {
     return(await Task.Run(() =>
     {
         var bytes = new byte[ReadBufferSize];
         //TODO: Allow for different interfaces and pipes...
         var isSuccess = WinUsbApiCalls.WinUsb_ReadPipe(_DefaultUsbInterface.Handle, _DefaultUsbInterface.ReadPipe.WINUSB_PIPE_INFORMATION.PipeId, bytes, ReadBufferSize, out var bytesRead, IntPtr.Zero);
         HandleError(isSuccess, "Couldn't read data");
         Tracer?.Trace(false, bytes);
         return bytes;
     }));
 }
Ejemplo n.º 8
0
        public void Dispose()
        {
            if (_IsDisposed)
            {
                return;
            }
            _IsDisposed = true;

            var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle);

            WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
        }
        private static ConnectedDeviceDefinition GetDeviceDefinition(SafeFileHandle defaultInterfaceHandle, string deviceId, ILogger logger)
        {
            var bufferLength = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));

#pragma warning disable IDE0059 // Unnecessary assignment of a value
            var isSuccess2 = WinUsbApiCalls.WinUsb_GetDescriptor(defaultInterfaceHandle, WinUsbApiCalls.DEFAULT_DESCRIPTOR_TYPE, 0, WinUsbApiCalls.EnglishLanguageID, out var _UsbDeviceDescriptor, bufferLength, out var lengthTransferred);
#pragma warning restore IDE0059 // Unnecessary assignment of a value
            _ = WindowsHelpers.HandleError(isSuccess2, "Couldn't get device descriptor", logger);

            string productName  = null;
            string serialNumber = null;
            string manufacturer = null;

            if (_UsbDeviceDescriptor.iProduct > 0)
            {
                productName = WinUsbApiCalls.GetDescriptor(
                    defaultInterfaceHandle,
                    _UsbDeviceDescriptor.iProduct,
                    "Couldn't get product name",
                    logger);
            }

            if (_UsbDeviceDescriptor.iSerialNumber > 0)
            {
                serialNumber = WinUsbApiCalls.GetDescriptor(
                    defaultInterfaceHandle,
                    _UsbDeviceDescriptor.iSerialNumber,
                    "Couldn't get serial number",
                    logger);
            }

            if (_UsbDeviceDescriptor.iManufacturer > 0)
            {
                manufacturer = WinUsbApiCalls.GetDescriptor(
                    defaultInterfaceHandle,
                    _UsbDeviceDescriptor.iManufacturer,
                    "Couldn't get manufacturer",
                    logger);
            }

            return(new ConnectedDeviceDefinition(
                       deviceId,
                       DeviceType.Usb,
                       productName: productName,
                       serialNumber: serialNumber,
                       manufacturer: manufacturer,
                       vendorId: _UsbDeviceDescriptor.idVendor,
                       productId: _UsbDeviceDescriptor.idProduct,
                       writeBufferSize: _UsbDeviceDescriptor.bMaxPacketSize0,
                       readBufferSize: _UsbDeviceDescriptor.bMaxPacketSize0
                       ));
        }
Ejemplo n.º 10
0
        public void Dispose()
        {
            if (_IsDisposed)
            {
                return;
            }
            _IsDisposed = true;

            //This is a native resource, so the IDisposable pattern should probably be implemented...
            var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle);

            WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
        }
Ejemplo n.º 11
0
        public override async Task WriteAsync(byte[] data)
        {
            await Task.Run(() =>
            {
                if (data.Length > WriteBufferSize)
                {
                    throw new Exception($"Data is longer than {WriteBufferSize} bytes which is the device's max buffer size.");
                }

                //TODO: Allow for different interfaces and pipes...
                var isSuccess = WinUsbApiCalls.WinUsb_WritePipe(_DefaultUsbInterface.Handle, _DefaultUsbInterface.WritePipe.WINUSB_PIPE_INFORMATION.PipeId, data, (uint)data.Length, out var bytesWritten, IntPtr.Zero);
                HandleError(isSuccess, "Couldn't write data");
                Tracer?.Trace(true, data);
            });
        }
Ejemplo n.º 12
0
        private WindowsUsbInterface GetInterface(SafeFileHandle interfaceHandle)
        {
            //TODO: We need to get the read/write size from a different API call...

            //TODO: Where is the logger/tracer?
            var isSuccess = WinUsbApiCalls.WinUsb_QueryInterfaceSettings(interfaceHandle, 0, out var interfaceDescriptor);

            var retVal = new WindowsUsbInterface(interfaceHandle, Logger, Tracer, interfaceDescriptor.bInterfaceNumber, _ReadBufferSize, _WriteBufferSize);

            WindowsDeviceBase.HandleError(isSuccess, "Couldn't query interface");

            for (byte i = 0; i < interfaceDescriptor.bNumEndpoints; i++)
            {
                isSuccess = WinUsbApiCalls.WinUsb_QueryPipe(interfaceHandle, 0, i, out var pipeInfo);
                WindowsDeviceBase.HandleError(isSuccess, "Couldn't query endpoint");
                retVal.UsbInterfaceEndpoints.Add(new WindowsUsbInterfaceEndpoint(pipeInfo.PipeId, pipeInfo.PipeType));
            }

            return(retVal);
        }
Ejemplo n.º 13
0
        private static UsbInterface GetInterface(SafeFileHandle interfaceHandle)
        {
            var retVal = new UsbInterface {
                Handle = interfaceHandle
            };
            var isSuccess = WinUsbApiCalls.WinUsb_QueryInterfaceSettings(interfaceHandle, 0, out var interfaceDescriptor);

            HandleError(isSuccess, "Couldn't query interface");

            retVal.USB_INTERFACE_DESCRIPTOR = interfaceDescriptor;

            for (byte i = 0; i < interfaceDescriptor.bNumEndpoints; i++)
            {
                isSuccess = WinUsbApiCalls.WinUsb_QueryPipe(interfaceHandle, 0, i, out var pipeInfo);
                HandleError(isSuccess, "Couldn't query pipe");
                retVal.UsbInterfacePipes.Add(new UsbInterfacePipe {
                    WINUSB_PIPE_INFORMATION = pipeInfo
                });
            }

            return(retVal);
        }
Ejemplo n.º 14
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;
            }
        }
Ejemplo n.º 15
0
        private void Initialize()
        {
            Dispose();

            int errorCode;

            if (string.IsNullOrEmpty(DeviceId))
            {
                throw new WindowsException($"{nameof(Device.Net.DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
            }

            _DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.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 Exception($"Device handle no good. Error code: {errorCode}");
                }
            }

            var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var defaultInterfaceHandle);

            HandleError(isSuccess, "Couldn't initialize device");

            var bufferLength = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));

            isSuccess = WinUsbApiCalls.WinUsb_GetDescriptor(defaultInterfaceHandle, WinUsbApiCalls.DEFAULT_DESCRIPTOR_TYPE, 0, EnglishLanguageID, out _UsbDeviceDescriptor, bufferLength, out var lengthTransferred);
            HandleError(isSuccess, "Couldn't get device descriptor");


            byte i = 0;

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

            _UsbInterfaces.Add(defaultInterface);

            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 Exception($"Could not enumerate interfaces for device {DeviceId}. Error code: { errorCode}");
                }

                var associatedInterface = GetInterface(interfacePointer);

                _UsbInterfaces.Add(associatedInterface);

                i++;
            }

            IsInitialized = true;
        }
        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;
            }
        }
Ejemplo n.º 17
0
        public void Dispose()
        {
            var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle);

            WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
        }