【问题标题】:Access USB port from C# and send and receive data从 C# 访问 USB 端口并发送和接收数据
【发布时间】:2010-11-24 13:55:59
【问题描述】:

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

【问题讨论】:

    标签: c# usb


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      有许多库可以完成这项工作。这是来自 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;
          }
      

      安卓

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

      【讨论】:

        【解决方案3】:

        这里有一些信息,还有一个图书馆:USB & C#

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

            如果你的USB设备类是HID你也可以试试thisC#驱动。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-08-06
              • 2012-01-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多