web-dev-qa-db-ja.com

C#からUSBポートにアクセスし、データを送受信します

C#でUSBポートにアクセスし、データストリームを送信し、他のデータを受信するにはどうすればよいですか?

11
kartal

そのための.netライブラリがあります:SharpUSBLib

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

4
Ali Tarhini

「USBポート」という用語は何の意味もありません。 USBのBは「バス」を意味し、any種類のデバイスがマシンと通信するための一般的な方法です。デバイスを使用可能にするには、ドライバーが必要です。ビデオカードとNICのドライバがあるのと同じです。

USBデバイスをユーザーモードコードから使用できるようにする一般的な方法は、ドライバーが旧式のシリアルポートをエミュレートすることです。 .NETではSerialPortクラスを使用します。デバイスの仕様をチェックして、そのドライバーが何をするかを確認してください。

3
Hans Passant

その仕事を成し遂げる多くの図書館があります。 Usb.Netの3つのプラットフォームのサンプルコードを次に示します( https://github.com/MelbourneDeveloper/Device.Net

Windows(WinUSB)

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

    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

ここにいくつかの情報とライブラリがあります: SB&C#

0
fARcRY

USBデバイスクラスがHIDの場合は、 this C#ドライバーを試すこともできます。

0
RHaguiuda

このサイトは間違いなくあなたを助けます... http://libusbdotnet.sourceforge.net
2010年にリリースされたクラスライブラリといくつかのサンプルコードが含まれています

0
saeed