--- source_files: - Common/DTS.Common.IConnection/USBConnection/USBFramework/FileIODeclarations.cs - Common/DTS.Common.IConnection/USBConnection/USBFramework/HIDDeclarations.cs - Common/DTS.Common.IConnection/USBConnection/USBFramework/DeviceManagementDeclarations.cs - Common/DTS.Common.IConnection/USBConnection/USBFramework/DeviceManagement.cs generated_at: "2026-04-16T02:09:55.521694+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "8939bee008e13a9a" --- # Documentation: USBFramework Module ## 1. Purpose This module provides low-level Windows API interop declarations and high-level device management utilities for USB device communication, specifically targeting HID-class devices and generic file I/O operations. It serves as the foundational layer for USB device enumeration, notification handling, and raw communication in the DTS system. The module exposes P/Invoke signatures for Windows kernel32.dll, hid.dll, setupapi.dll, and advapi32.dll functions, alongside managed wrappers (e.g., `DeviceManagement`) that abstract device discovery, registration for plug-and-play events, and property retrieval. Its role is to enable reliable detection, connection, and interaction with USB devices without relying on higher-level .NET USB libraries. ## 2. Public Interface ### `FileIODeclarations` class (namespace `DTS.Common.USBFramework`) - **`const uint GENERIC_READ = 0x80000000`** Access mask for read operations in `CreateFile`. - **`const uint GENERIC_WRITE = 0x40000000`** Access mask for write operations in `CreateFile`. - **`const uint FILE_SHARE_READ = 0x00000001`** Share mode flag for read sharing. - **`const uint FILE_SHARE_WRITE = 0x00000002`** Share mode flag for write sharing. - **`const uint FILE_FLAG_OVERLAPPED = 0x40000000`** Flag for asynchronous I/O in `CreateFile`. - **`const int INVALID_HANDLE_VALUE = -1`** Sentinel value for invalid handle. - **`const short OPEN_EXISTING = 3`** Creation disposition for opening existing files/devices. - **`const int WAIT_TIMEOUT = 0x102`**, **`WAIT_OBJECT_0 = 0`**, **`WAIT_FAILED = 0xFFFFFFFF`**, **`WAIT_ABANDONED = 0x00000080`** Return codes for `WaitForSingleObject`. - **`const int FSCTL_SET_COMPRESSION = 0x9C040`** I/O control code for compression (unused in current context). - **`struct OVERLAPPED`** Unmanaged structure for asynchronous I/O (note: `hEvent` is `int`, not `IntPtr`). - **`struct SECURITY_ATTRIBUTES`** Unmanaged structure for security descriptor handling (note: `lpSecurityDescriptor` is `int`, not `IntPtr`). - **`int CancelIo(int hFile)`** Cancels pending I/O operations on the specified file handle. - **`int CloseHandle(int hObject)`** Closes an open object handle. - **`int CreateEvent(ref SECURITY_ATTRIBUTES SecurityAttributes, int bManualReset, int bInitialState, string lpName)`** Creates or opens a named or unnamed event object. - **`int CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, uint dwFlagsAndAttributes, int hTemplateFile)`** Creates or opens a file or I/O device (e.g., USB device). - **`int GetLastError()`** Retrieves the calling thread’s last-error code. - **`int ReadFile(int hFile, ref byte lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int lpOverlapped)`** Reads from a file or device (note: `lpOverlapped` is `int`, not `ref OVERLAPPED`). - **`uint WaitForSingleObject(int hHandle, int dwMilliseconds)`** Waits until the specified object is in the signaled state or the time-out interval elapses. - **`int WriteFile(int hFile, ref byte lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, int lpOverlapped)`** Writes to a file or device. - **`int DeviceIoControl(IntPtr hDevice, int dwIoControlCode, ref short lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, ref int lpBytesReturned, IntPtr lpOverlapped)`** Sends a control code directly to a device driver. ### `FileIO` class (namespace `DTS.Common.USBFramework`) - **`const short FILE_ATTRIBUTE_NORMAL = 0x80`**, **`FILE_FLAG_OVERLAPPED = 0x40000000`**, etc. Duplicate constants (with different types) from `FileIODeclarations`. - **`struct SECURITY_ATTRIBUTES`** Alternate definition with `lpSecurityDescriptor` as `IntPtr` (inconsistent with `FileIODeclarations`). - **`bool CloseHandle(SafeFileHandle hObject)`** Managed wrapper for closing a `SafeFileHandle`. - **`SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile)`** Managed wrapper returning `SafeFileHandle`. ### `HIDDeclarations` class (namespace `DTS.DASLib.Connection.USBFramework`) - **`const short HidP_Input = 0`, `HidP_Output = 1`, `HidP_Feature = 2`** Report types for HID operations. - **`struct HIDD_ATTRIBUTES`** Contains vendor ID, product ID, and version number. - **`struct HIDP_CAPS`** Contains HID device capabilities (report sizes, usage pages, etc.). - **`struct HidP_Value_Caps`** Describes value capabilities (e.g., range, usage, min/max). - **`bool HidD_FlushQueue(int HidDeviceObject)`** Flushes the input buffer of an HID device. - **`bool HidD_FreePreparsedData(ref IntPtr PreparsedData)`** Frees preparsed data allocated by `HidD_GetPreparsedData`. - **`int HidD_GetAttributes(int HidDeviceObject, ref HIDD_ATTRIBUTES Attributes)`** Retrieves device attributes (VID, PID, version). - **`bool HidD_GetFeature(int HidDeviceObject, ref byte lpReportBuffer, int ReportBufferLength)`** Retrieves a feature report from the device. - **`bool HidD_GetInputReport(int HidDeviceObject, ref byte lpReportBuffer, int ReportBufferLength)`** Retrieves an input report from the device. - **`void HidD_GetHidGuid(ref Guid HidGuid)`** Retrieves the system-defined GUID for HID devices. - **`bool HidD_GetNumInputBuffers(int HidDeviceObject, ref int NumberBuffers)`** Gets the number of input buffers allocated for the device. - **`bool HidD_GetPreparsedData(int HidDeviceObject, ref IntPtr PreparsedData)`** Retrieves preparsed data for HID device. - **`bool HidD_SetFeature(int HidDeviceObject, ref byte lpReportBuffer, int ReportBufferLength)`** Sends a feature report to the device. - **`bool HidD_SetNumInputBuffers(int HidDeviceObject, int NumberBuffers)`** Sets the number of input buffers. - **`bool HidD_SetOutputReport(int HidDeviceObject, ref byte lpReportBuffer, int ReportBufferLength)`** Sends an output report to the device. - **`int HidP_GetCaps(IntPtr PreparsedData, ref HIDP_CAPS Capabilities)`** Retrieves HID capabilities from preparsed data. - **`int HidP_GetValueCaps(short ReportType, ref byte ValueCaps, ref short ValueCapsLength, IntPtr PreparsedData)`** Retrieves value capability information. ### `DeviceManagement` class (namespace `DTS.Common.USBFramework`) - **`bool DeviceNameMatch(Message m, string mydevicePathName)`** Compares the device path in a `WM_DEVICECHANGE` message with `mydevicePathName`. Returns `true` if they match (case-insensitive). Uses `DEV_BROADCAST_DEVICEINTERFACE_1` to extract the device name from the message’s `LParam`. - **`bool FindDeviceFromGuid(Guid myGuid, ref string[] devicePathName)`** Enumerates devices in the interface class specified by `myGuid` and populates `devicePathName` with their device paths. Returns `true` if at least one device is found. Uses `SetupDiGetClassDevs`, `SetupDiEnumDeviceInterfaces`, and `SetupDiGetDeviceInterfaceDetail`. - **`bool RegisterForDeviceNotifications(IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)`** Registers a window (`formHandle`) to receive `WM_DEVICECHANGE` notifications for devices in `classGuid`. Returns `true` on success. Allocates unmanaged memory for `DEV_BROADCAST_DEVICEINTERFACE` and calls `RegisterDeviceNotification`. - **`void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle)`** Unregisters device notifications using `UnregisterDeviceNotification`. Ignores failures. - **`bool GetDeviceRegistryProperty(Guid myGuid)`** Enumerates devices in `myGuid`’s class and retrieves the `SPDRP_DRIVER` registry property for each device. Logs results via `APILogger`. Returns `true` on success (even if no devices found). ## 3. Invariants - **Handle Validity**: All handle-based APIs (`CreateFile`, `RegisterDeviceNotification`) return `INVALID_HANDLE_VALUE` (-1) or `IntPtr.Zero` on failure. Callers must check return values before use. - **Memory Management**: Unmanaged memory allocated via `Marshal.AllocHGlobal` (e.g., in `FindDeviceFromGuid`, `RegisterForDeviceNotifications`) must be freed with `Marshal.FreeHGlobal`. The `DeviceManagement` class handles this in `try/finally` blocks. - **Structure Size Consistency**: The `cbSize` field of `SP_DEVICE_INTERFACE_DETAIL_DATA` must be set to `Marshal.SizeOf()` *before* calling `SetupDiGetDeviceInterfaceDetail`. The implementation writes `cbSize` manually to the unmanaged buffer, with logic to handle 32/64-bit alignment. - **64-bit Compatibility**: `IS64_BIT_PROCESS` (set via `IntPtr.Size == 8`) is used to adjust pointer arithmetic (e.g., `cbSize` offset, handle comparison). This is critical for `FindDeviceFromGuid` and `RegisterForDeviceNotifications`. - **HID Report Buffer Size**: `HidD_GetFeature`, `HidD_SetFeature`, etc., require the report buffer to be exactly `InputReportByteLength`/`OutputReportByteLength`/`FeatureReportByteLength` bytes (from `HIDP_CAPS`), including the report ID byte. - **GUID Consistency**: The `HidD_GetHidGuid` function populates a `Guid` by reference; callers must pass a valid `Guid` instance (not `Guid.Empty`). ## 4. Dependencies ### Imports/References: - **System.Runtime.InteropServices**: Required for P/Invoke, `Marshal`, `StructLayout`. - **Microsoft.Win32.SafeHandles**: Used in `FileIO.CloseHandle` (via `SafeFileHandle`). - **System.Windows.Forms**: Required for `Message` type in `DeviceNameMatch`. - **DTS.Common.Utilities.Logging**: Used for `APILogger.Log` in `GetDeviceRegistryProperty`. - **hid.dll**, **setupapi.dll**, **kernel32.dll**, **advapi32.dll**: Native libraries for HID, device setup, and registry operations. ### Dependencies on Other Modules: - **`DeviceManagement`** depends on `DeviceManagementDeclarations` for unmanaged API declarations. - **`FileIO`** and **`FileIODeclarations`** provide overlapping declarations (likely legacy duplication). - **`HIDDeclarations`** is in a different namespace (`DTS.DASLib.Connection.USBFramework`) and is used by HID-specific communication logic (not shown here). ### Used By: - Higher-level USB connection classes (e.g., `USBConnection`, `HIDConnection`) that consume `DeviceManagement` for device discovery and `HIDDeclarations` for HID I/O. ## 5. Gotchas - **Duplicate Constants**: `FileIO` and `FileIODeclarations` define identical constants (e.g., `GENERIC_READ`, `FILE_FLAG_OVERLAPPED`) with inconsistent types (`uint` vs `short`/`int`). This may cause confusion or errors if mixed. - **Inconsistent Structure Definitions**: `SECURITY_ATTRIBUTES` is defined twice in `FileIODeclarations` and `FileIO` with different field types (`int` vs `IntPtr`). This is unsafe and may cause crashes on 64-bit systems. - **`OVERLAPPED` Structure**: The `OVERLAPPED` struct uses `int` for `hEvent` instead of `IntPtr`, which is incorrect for 64-bit compatibility. This will fail on 64-bit processes. - **`CreateFile` Overloads**: `FileIODeclarations.CreateFile` returns `int` (unmanaged handle), while `FileIO.CreateFile` returns `SafeFileHandle`. Using the wrong overload may lead to resource leaks or handle misuse. - **`RegisterForDeviceNotifications` Memory Leak Risk**: The `buffer` allocated via `Marshal.AllocHGlobal` is freed *after* `RegisterDeviceNotification`, but if `RegisterDeviceNotification` fails, the handle is `IntPtr.Zero`, and the buffer is still freed. This is safe, but the comment `// Set fDeleteOld True to prevent memory leaks` is misleading—the `true` flag in `StructureToPtr` overwrites the old pointer, but `AllocHGlobal`/`FreeHGlobal` is still required. - **`FindDeviceFromGuid` Buffer Size Calculation**: The `cbSize` offset calculation `(IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8` assumes `cbSize` is 4 bytes on 32-bit and 8 on 64-bit, but `SP_DEVICE_INTERFACE_DETAIL_DATA.cbSize` is `int` (4 bytes) regardless of platform. This may cause misalignment on 64-bit. - **`DeviceNameMatch` String Size Calculation**: Assumes `dbcc_name` is Unicode (2 bytes/char) and subtracts 28 bytes for fixed fields. This is correct for `DEV_BROADCAST_DEVICEINTERFACE_1` but may break if structure layout changes. - **`GetDeviceRegistryProperty` Registry Key Access**: Uses `SetupDiOpenDevRegKey` but does not show its usage; the implementation only retrieves `SPDRP_DRIVER` via `SetupDiGetDeviceRegistryPropertyA`. Registry access may fail without elevated privileges. - **`HIDP_*` Functions**: Return codes (e.g., `HidP_GetCaps`) are `int` but not documented. Callers must check for success (typically `0` for success, non-zero for error codes like `HIDP_STATUS_BUFFER_TOO_SMALL`). - **No Async Support**: Despite `FILE_FLAG_OVERLAPPED` being defined, the `ReadFile`/`WriteFile` declarations use synchronous signatures (no `OVERLAPPED` pointer). Asynchronous I/O is not implemented.