Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common.IConnection/USBConnection/HIDUSBConnection.md
2026-04-17 14:55:32 -04:00

9.5 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common.IConnection/USBConnection/HIDUSBConnection/HIDUSBConnection.cs
2026-04-16T02:10:22.619594+00:00 Qwen/Qwen3-Coder-Next-FP8 1 4a9eeb7b8043999a

Documentation: HIDUSBConnection Class

1. Purpose

HIDUSBConnection is a concrete implementation of the IConnection interface that enables communication with a specific HID-class USB device (identified by Vendor ID 0x1CB9 and Product ID 0x0003, named HIDSLICE) using Windows file I/O APIs (CreateFile, ReadFile, WriteFile via overlapped I/O). It abstracts low-level HID report handling (input/output reports) over USB, providing asynchronous send/receive semantics consistent with .NETs IAsyncResult pattern. This module exists to support direct, low-latency data transfer to/from embedded hardware (e.g., a data acquisition recorder) where standard socket-based communication is not applicable.


2. Public Interface

Constructors & Finalizer

  • HIDUSBConnection()
    Initializes the instance, sets up SECURITY_ATTRIBUTES for CreateFile, and initializes _Connected = false.

  • ~HIDUSBConnection()
    Finalizer that invokes Dispose(false) to release unmanaged resources.

Disposal

  • void Dispose()
    Performs deterministic cleanup: calls Dispose(true) and suppresses finalization.

  • protected virtual void Dispose(bool disposing)
    Releases all handles (_HIDHandle, _ReadHandle, _WriteHandle) via FileIODeclarations.CloseHandle, disposes _MyHID, and sets _Connected = false. Idempotent (disposed flag prevents double-disposal).

Connection Management

  • void Create(string ConnectString)
    Stores the device path (ConnectString) for later use in EndConnect. Does not open the device.

  • IAsyncResult BeginConnect(AsyncCallback cb, object state)
    Initiates asynchronous connection. Enqueues a work item to invoke NetCallbackFix, which in turn invokes the callback on the thread pool. Actual device opening occurs in EndConnect.

  • void EndConnect(IAsyncResult ar)
    Opens the device using ConnectString (set via Create) via three CreateFile calls:

    • _HIDHandle: for attribute queries (no access rights)
    • _ReadHandle: for reading input reports (GENERIC_READ)
    • _WriteHandle: for writing output reports (GENERIC_WRITE)
      Retrieves device attributes (HidD_GetAttributes), capabilities (GetDeviceCapabilities), and input report buffer size (GetInputReportBufferSize). Flushes the input queue. Sets _Connected = true. Throws on handle failure or attribute retrieval failure.
  • IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback cb, object state)
    Asynchronous disconnect. Enqueues a work item to invoke the callback. Actual cleanup is deferred to EndDisconnect.

  • void EndDisconnect(IAsyncResult asyncResult)
    Closes all three handles (_HIDHandle, _ReadHandle, _WriteHandle) and sets _Connected = false.

Properties

  • bool Connected { get; }
    Returns _Connected.

  • string ConnectString { get; }
    Returns Device_Name (set via Create).

  • System.Net.Sockets.SocketFlags Flags { get; set; }
    Property required by IConnection interface; unused in this implementation.

  • string GetConnectionData()
    Returns "" (empty string). No meaningful data exposed.

  • double GetCurrentDownloadRate()
    Returns 0D. Rate tracking not implemented.

  • double GetCurrentUploadRate()
    Returns 0D. Rate tracking not implemented.

Static Utility

  • static string GetFirstConnectString()
    Scans all HID devices on the system to find the first device matching DTS_VID (0x1CB9) and HIDSLICE_PID (0x0003). Returns the devices path string (e.g., \\?\hid#vid_1cb9&pid_0003#...) or string.Empty if not found. Uses HIDDeclarations.HidD_GetHidGuid, DeviceManagement.FindDeviceFromGuid, and HIDDeclarations.HidD_GetAttributes.

I/O Operations

  • IAsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncCallback cb, object state)
    Initiates asynchronous send. Validates _ReadHandle and _WriteHandle are valid. Enqueues callback via ThreadPool.QueueUserWorkItem. Actual transmission occurs in EndSend.

  • int EndSend(IAsyncResult ar)
    Writes buffer[offset..offset+size) to the device in chunks, respecting OutputReportByteLength.

    • Prepends each chunk with report ID 0x00 at index 0.
    • Uses HIDevice.OutputReport.Write for each chunk.
      Returns size (number of bytes sent). Throws on invalid handles or write failure.
  • IAsyncResult BeginReceive(byte[] buffer, int offset, int size, AsyncCallback cb, object state)
    Initiates asynchronous receive. Validates handles. Enqueues callback. Actual read occurs in EndReceive.

  • int EndReceive(IAsyncResult ar)
    Reads one input report into InputReportBuffer via HIDevice.InputReport.Read. Copies data (skipping report ID at index 0) into buffer[offset..]. Returns size if successful, 0 otherwise. Sets IsCompleted = true and signals AsyncWaitHandle.

Unsupported Operations (Throw NotSupportedException)

  • BeginAccept, EndAccept, Bind(int), Listen(int)
    These methods are implemented only to satisfy IConnection but are not applicable to HID device communication.

3. Invariants

  • Device Identity: Only devices with VendorID == 0x1CB9 and ProductID == 0x0003 are accepted.
  • Handle State: _HIDHandle, _ReadHandle, and _WriteHandle must be valid (non-INVALID_HANDLE_VALUE) before BeginSend/BeginReceive succeeds.
  • Connection State: _Connected is true only after successful completion of EndConnect, and false otherwise (including after EndDisconnect or disposal).
  • Report Structure:
    • Input reports: Data starts at index 1; index 0 is the report ID (ignored).
    • Output reports: Data starts at index 1; index 0 is report ID (set to 0).
  • Buffer Size: InputReportBuffer is sized to _MyHID.Capabilities.InputReportByteLength during EndConnect.
  • Disposal Safety: Dispose is idempotent (disposed flag prevents re-entry).
  • Asynchronous Pattern: All async operations (BeginConnect, BeginSend, etc.) use HIDUSBRecAsyncResult and delegate callback invocation to NetCallbackFix, which runs on a thread pool thread.

4. Dependencies

External Dependencies

  • Windows API (via interop):
    • FileIODeclarations.CreateFile, CloseHandle, FILE_SHARE_*, GENERIC_*, INVALID_HANDLE_VALUE, OPEN_EXISTING
    • HIDDeclarations.HidD_GetHidGuid, HidD_GetAttributes
  • DTS.DASLib.Connection.USBFramework:
    • HIDevice class (used for device attributes, capabilities, input/output report handling)
    • DeviceManagement class (used in GetFirstConnectString)
  • DTS.DASLib.DASResource:
    • Strings resource class (for localized error messages, e.g., Strings.HIDUSBConnection_EndConnect_Err1)
  • .NET Framework Core:
    • System.Runtime.InteropServices (for Marshal.SizeOf, SECURITY_ATTRIBUTES)
    • System.Threading (for ThreadPool, ManualResetEvent)
    • System.Windows.Forms.MessageBox (used in NetCallbackFix for exception reporting—potential runtime dependency on WinForms).

Implemented Interfaces

  • IConnection (interface defining the contract; not shown in source but referenced).

Inferred Consumers

  • Any code requiring IConnection to communicate with the HIDSLICE device (e.g., data acquisition logic, device enumeration UI).
  • GetFirstConnectString is likely called by device discovery components.

5. Gotchas

  • Misleading Async Pattern: BeginConnect/BeginSend/BeginReceive do not perform actual I/O; they only enqueue a callback. All work happens in End* methods. This deviates from typical .NET async patterns where Begin* initiates the operation.
  • No Overlapped I/O: Despite using CreateFile with overlapped semantics (implied by _ReadHandle/_WriteHandle), the code does not use OVERLAPPED structures or ReadFile/WriteFile with completion callbacks. Instead, it relies on synchronous HIDevice.InputReport.Read/Write, which may block the thread pool thread.
  • Hardcoded Report ID: Output reports always use 0x00 as the report ID. This assumes the device expects report ID 0; mismatched IDs will cause silent failures or device errors.
  • WinForms Dependency in Error Handling: NetCallbackFix shows a MessageBox on exceptions—a severe anti-pattern for non-UI threads or server environments.
  • GetFirstConnectString Hack: The method scans all HID devices and stops at the first match. If multiple HIDSLICE devices are connected, behavior is undefined (first found wins).
  • Buffer Size Mismatch in EndReceive: EndReceive copies InputReportBuffer.Length - 1 bytes into the user buffer, but returns rar.size regardless. If rar.size < InputReportBuffer.Length - 1, the caller may read uninitialized buffer data beyond the actual received payload.
  • No Timeout Handling: No mechanism for read/write timeouts; operations may block indefinitely.
  • Flags Property Unused: The SocketFlags property is implemented but never used.
  • BeginAccept/EndAccept Misuse: Throwing NotSupportedException for connection-oriented methods suggests this class was adapted from a socket-based IConnection implementation without full refactoring.