/src/WinUsb/WinUsb.Helpers.cs

https://github.com/AArnott/pinvoke · C# · 127 lines · 76 code · 9 blank · 42 comment · 6 complexity · 3c0b52757d2e8f7e6bf2bf2f733382ce MD5 · raw file

  1. // Copyright © .NET Foundation and Contributors. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. namespace PInvoke
  4. {
  5. using System;
  6. using System.Runtime.InteropServices;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. /// <content>
  10. /// Methods and nested types that are not strictly P/Invokes but provide
  11. /// a slightly higher level of functionality to ease calling into native code.
  12. /// </content>
  13. public static partial class WinUsb
  14. {
  15. /// <summary>
  16. /// Asynchronously reads data from the specified pipe.
  17. /// </summary>
  18. /// <param name="interfaceHandle">
  19. /// An opaque handle to the interface that contains the endpoint with which the pipe is associated.
  20. /// </param>
  21. /// <param name="pipeID">
  22. /// <paramref name="pipeID"/> corresponds to the bEndpointAddress field in the endpoint descriptor.
  23. /// </param>
  24. /// <param name="buffer">
  25. /// A caller-allocated buffer that receives the data that is read.
  26. /// </param>
  27. /// <param name="cancellationToken">
  28. /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
  29. /// </param>
  30. /// <returns>
  31. /// A <see cref="ValueTask"/> which represents the asynchronous operation, and returns the number of bytes transferred.
  32. /// </returns>
  33. public static unsafe ValueTask<int> WinUsb_ReadPipeAsync(SafeUsbHandle interfaceHandle, byte pipeID, Memory<byte> buffer, CancellationToken cancellationToken)
  34. {
  35. var overlapped = new WinUsbOverlapped(interfaceHandle, pipeID, buffer, cancellationToken);
  36. var nativeOverlapped = overlapped.Pack();
  37. if (WinUsb_ReadPipe(
  38. interfaceHandle,
  39. pipeID,
  40. (byte*)overlapped.BufferHandle.Pointer,
  41. buffer.Length,
  42. out int lengthTransferred,
  43. nativeOverlapped))
  44. {
  45. overlapped.Unpack();
  46. return new ValueTask<int>(lengthTransferred);
  47. }
  48. else
  49. {
  50. var error = (Win32ErrorCode)Marshal.GetLastWin32Error();
  51. if (error == Win32ErrorCode.ERROR_IO_PENDING)
  52. {
  53. return new ValueTask<int>(overlapped.Completion);
  54. }
  55. else
  56. {
  57. overlapped.Unpack();
  58. #if NET45
  59. return new ValueTask<int>(Task.Run(new Func<int>(() => throw new Win32Exception(error))));
  60. #else
  61. return new ValueTask<int>(Task.FromException<int>(new PInvoke.Win32Exception(error)));
  62. #endif
  63. }
  64. }
  65. }
  66. /// <summary>
  67. /// Asynchronously writes data to a pipe.
  68. /// </summary>
  69. /// <param name="interfaceHandle">
  70. /// An opaque handle to the interface that contains the endpoint with which the pipe is associated.
  71. /// </param>
  72. /// <param name="pipeID">
  73. /// PipeID corresponds to the bEndpointAddress field in the endpoint descriptor.
  74. /// </param>
  75. /// <param name="buffer">
  76. /// A caller-allocated buffer that contains the data to write.
  77. /// </param>
  78. /// <param name="cancellationToken">
  79. /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous operation.
  80. /// </param>
  81. /// <returns>
  82. /// A <see cref="ValueTask"/> which represents the asynchronous operation, and returns the number of bytes transferred.
  83. /// </returns>
  84. public static unsafe ValueTask<int> WinUsb_WritePipeAsync(SafeUsbHandle interfaceHandle, byte pipeID, Memory<byte> buffer, CancellationToken cancellationToken)
  85. {
  86. var overlapped = new WinUsbOverlapped(interfaceHandle, pipeID, buffer, cancellationToken);
  87. var nativeOverlapped = overlapped.Pack();
  88. if (WinUsb_WritePipe(
  89. interfaceHandle,
  90. pipeID,
  91. (byte*)overlapped.BufferHandle.Pointer,
  92. buffer.Length,
  93. out int lengthTransferred,
  94. nativeOverlapped))
  95. {
  96. overlapped.Unpack();
  97. return new ValueTask<int>(lengthTransferred);
  98. }
  99. else
  100. {
  101. var error = (Win32ErrorCode)Marshal.GetLastWin32Error();
  102. if (error == Win32ErrorCode.ERROR_IO_PENDING)
  103. {
  104. return new ValueTask<int>(overlapped.Completion);
  105. }
  106. else
  107. {
  108. overlapped.Unpack();
  109. #if NET45
  110. return new ValueTask<int>(Task.Run(new Func<int>(() => throw new Win32Exception(error))));
  111. #else
  112. return new ValueTask<int>(Task.FromException<int>(new PInvoke.Win32Exception(error)));
  113. #endif
  114. }
  115. }
  116. }
  117. }
  118. }