13

How to access a USB port in C#, send a data stream and receive other data?

ЯegDwight
25.3k10 gold badges47 silver badges52 bronze badges
asked Nov 24, 2010 at 13:55
0

5 Answers 5

5

there's a .net library for that: SharpUSBLib

http://www.icsharpcode.net/OpenSource/SharpUSBLib/default.aspx

answered Nov 24, 2010 at 13:59
Sign up to request clarification or add additional context in comments.

Comments

1

There are many libraries that achieve the job. Here is sample code for three platforms from Usb.Net (https://github.com/MelbourneDeveloper/Device.Net)

Windows (WinUSB)

https://github.com/MelbourneDeveloper/Device.Net/blob/411fea4acfbf965fc0160bf728a46b5ded8abc5d/src/Usb.Net/Windows/WindowsUsbDevice.cs#L33

 public override Task InitializeAsync()
 {
 Dispose();
 int errorCode;
 if (string.IsNullOrEmpty(DeviceId))
 {
 throw new WindowsException($"{nameof(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, 0, 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;
 RaiseConnected();
 return Task.CompletedTask;
 }
 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 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);
 });
 }

UWP

https://github.com/MelbourneDeveloper/Device.Net/blob/411fea4acfbf965fc0160bf728a46b5ded8abc5d/src/Usb.Net.UWP/UWPUsbDevice.cs#L24

 public override async Task InitializeAsync()
 {
 await GetDevice(DeviceId);
 if (_ConnectedDevice != null)
 {
 var usbInterface = _ConnectedDevice.Configuration.UsbInterfaces.FirstOrDefault();
 if (usbInterface == null)
 {
 _ConnectedDevice.Dispose();
 throw new Exception("There was no Usb Interface found for the device.");
 }
 var interruptPipe = usbInterface.InterruptInPipes.FirstOrDefault();
 if (interruptPipe == null)
 {
 throw new Exception("There was no interrupt pipe found on the interface");
 }
 interruptPipe.DataReceived += InterruptPipe_DataReceived;
 RaiseConnected();
 }
 else
 {
 throw new Exception($"Could not connect to device with Device Id {DeviceId}. Check that the package manifest has been configured to allow this device.");
 }
 }
 public override async Task WriteAsync(byte[] bytes)
 {
 var bufferToSend = bytes.AsBuffer();
 var usbInterface = _ConnectedDevice.Configuration.UsbInterfaces.FirstOrDefault();
 var outPipe = usbInterface.InterruptOutPipes.FirstOrDefault();
 await outPipe.OutputStream.WriteAsync(bufferToSend);
 Tracer?.Trace(false, bytes);
 }
 public override async Task<byte[]> ReadAsync()
 {
 if (_IsReading)
 {
 throw new Exception("Reentry");
 }
 lock (_Chunks)
 {
 if (_Chunks.Count > 0)
 {
 var retVal = _Chunks[0];
 Tracer?.Trace(false, retVal);
 _Chunks.RemoveAt(0);
 return retVal;
 }
 }
 _IsReading = true;
 _TaskCompletionSource = new TaskCompletionSource<byte[]>();
 return await _TaskCompletionSource.Task;
 }

Android

https://github.com/MelbourneDeveloper/Device.Net/blob/411fea4acfbf965fc0160bf728a46b5ded8abc5d/src/Usb.Net.Android/AndroidUsbDevice.cs#L199

 public async Task InitializeAsync()
 {
 //TODO: Use a semaphore lock here
 if (_IsInitializing)
 {
 return;
 }
 _IsInitializing = true;
 try
 {
 //TODO:
 //Dispose();
 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");
 }
 var usbInterface = _UsbDevice.GetInterface(0);
 //TODO: This selection stuff needs to be moved up higher. The constructor should take these arguments
 for (var i = 0; i < usbInterface.EndpointCount; i++)
 {
 var ep = usbInterface.GetEndpoint(i);
 if (_ReadEndpoint == null && ep.Type == UsbAddressing.XferInterrupt && ep.Address == (UsbAddressing)129)
 {
 _ReadEndpoint = ep;
 continue;
 }
 if (_WriteEndpoint == null && ep.Type == UsbAddressing.XferInterrupt && (ep.Address == (UsbAddressing)1 || ep.Address == (UsbAddressing)2))
 {
 _WriteEndpoint = ep;
 }
 }
 //TODO: This is a bit of a guess. It only kicks in if the previous code fails. This needs to be reworked for different devices
 if (_ReadEndpoint == null)
 {
 _ReadEndpoint = usbInterface.GetEndpoint(0);
 }
 if (_WriteEndpoint == null)
 {
 _WriteEndpoint = usbInterface.GetEndpoint(1);
 }
 if (_ReadEndpoint.MaxPacketSize != ReadBufferLength)
 {
 throw new Exception("Wrong packet size for read endpoint");
 }
 if (_WriteEndpoint.MaxPacketSize != ReadBufferLength)
 {
 throw new Exception("Wrong packet size for write endpoint");
 }
 _UsbDeviceConnection = UsbManager.OpenDevice(_UsbDevice);
 if (_UsbDeviceConnection == null)
 {
 throw new Exception("could not open connection");
 }
 if (!_UsbDeviceConnection.ClaimInterface(usbInterface, true))
 {
 throw new Exception("could not claim interface");
 }
 Logger.Log("Hid device initialized. About to tell everyone.", null, LogSection);
 IsInitialized = true;
 RaiseConnected();
 return;
 }
 catch (Exception ex)
 {
 Logger.Log("Error initializing Hid Device", ex, LogSection);
 }
 _IsInitializing = false;
 }
 public override async Task<byte[]> ReadAsync()
 {
 try
 {
 var byteBuffer = ByteBuffer.Allocate(ReadBufferLength);
 var request = new UsbRequest();
 request.Initialize(_UsbDeviceConnection, _ReadEndpoint);
 request.Queue(byteBuffer, ReadBufferLength);
 await _UsbDeviceConnection.RequestWaitAsync();
 var buffers = new byte[ReadBufferLength];
 byteBuffer.Rewind();
 for (var i = 0; i < ReadBufferLength; i++)
 {
 buffers[i] = (byte)byteBuffer.Get();
 }
 //Marshal.Copy(byteBuffer.GetDirectBufferAddress(), buffers, 0, ReadBufferLength);
 Tracer?.Trace(false, buffers);
 return buffers;
 }
 catch (Exception ex)
 {
 Logger.Log(Helpers.ReadErrorMessage, ex, LogSection);
 throw new IOException(Helpers.ReadErrorMessage, ex);
 }
 }
 public override async Task WriteAsync(byte[] data)
 {
 try
 {
 var request = new UsbRequest();
 request.Initialize(_UsbDeviceConnection, _WriteEndpoint);
 var byteBuffer = ByteBuffer.Wrap(data);
 Tracer?.Trace(true, data);
 request.Queue(byteBuffer, data.Length);
 await _UsbDeviceConnection.RequestWaitAsync();
 }
 catch (Exception ex)
 {
 Logger.Log(Helpers.WriteErrorMessage, ex, LogSection);
 throw new IOException(Helpers.WriteErrorMessage, ex);
 }
 }
answered Dec 28, 2018 at 6:32

Comments

0

Heres some information, and a library: USB & C#

answered Nov 24, 2010 at 14:04

Comments

0

this site definitely help u... http://libusbdotnet.sourceforge.net
it contains a class library and some sample codes release on 2010

answered Sep 24, 2012 at 6:25

Comments

0

If you USB device Class is HID you can also try this C# driver.

answered Aug 21, 2014 at 12:25

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.