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

13 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/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
2026-04-16T02:09:55.521694+00:00 Qwen/Qwen3-Coder-Next-FP8 1 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 threads 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 messages 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 myGuids 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.