从C#访问USB端口并发送和接收数据

时间:2010-11-24 13:56:00

标签: c# usb

如何访问C#中的USB端口,发送数据流并接收其他数据?

6 个答案:

答案 0 :(得分:4)

答案 1 :(得分:4)

术语“usb port”并不意味着什么。 USB中的B表示“总线”,它是任何类型设备与机器通信的通用方式。需要驱动程序才能使设备可用。正如您有视频卡和NIC的驱动程序一样。

使用USB模式代码的常用方法是让驱动程序模拟旧式串行端口。您将在.NET中使用SerialPort类。检查设备的规格,看看它的驱动程序是什么。

答案 2 :(得分:0)

下载一些信息和图书馆:USB & C#

答案 3 :(得分:0)

这个网站绝对有帮助你... http://libusbdotnet.sourceforge.net
它包含一个类库和2010年发布的一些示例代码

答案 4 :(得分:0)

如果USB设备类是HID,您也可以尝试使用this C#驱动程序。

答案 5 :(得分:0)

有许多图书馆可以完成这项工作。这是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

<img src="{{wing.icon.name}}" class="{{wing.icon.name}}"
       #wingIconElm
       *ngIf="menuConfig.showIcons || menuConfig.onlyIcons"
       [ngStyle]="{
            'color': wing.icon.color || menuConfig.wingFontColor,
            'font-size': iconSize + 'px',
            'width': iconSize + 'px',
            'height': iconSize + 'px'
       }">

UWP

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

    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);
        });
    }

Android

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

    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;
    }