--- source_files: - Common/DTS.Common.IConnection/USBConnection/HIDUSBConnection/HIDUSBConnection.cs generated_at: "2026-04-16T02:10:22.619594+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "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 .NET’s `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 device’s 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.