Access USB port from C# and send and receive data

后端 未结 6 1698
终归单人心
终归单人心 2021-02-19 12:04

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

相关标签:
6条回答
  • 2021-02-19 12:09

    The term "usb port" doesn't mean anything. The B in USB means "bus", it is a generic way for any kind of device to talk to the machine. A driver is required to make the device usable. Just as you have drivers for your video card and your NIC.

    A common way make USB device usable from user mode code is for the driver to emulate an old-fashioned serial port. You'd use the SerialPort class in .NET. Check the specs of the device to see what its driver does.

    0 讨论(0)
  • 2021-02-19 12:17

    there's a .net library for that: SharpUSBLib

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

    0 讨论(0)
  • 2021-02-19 12:25

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

    0 讨论(0)
  • 2021-02-19 12:27

    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);
            }
        }
    
    0 讨论(0)
  • 2021-02-19 12:27

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

    0 讨论(0)
  • 2021-02-19 12:27

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

    0 讨论(0)
提交回复
热议问题