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); }
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); }
//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); }
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++; } }
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); }); }
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); })); }
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; })); }
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 )); }
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"); }
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); }); }
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); }
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); }
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; } }
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; } }
public void Dispose() { var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle); WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed"); }