--- source_files: - Common/DTS.Common.IConnection/USBConnection/WINUSBConnection/WINUSBDeviceApi.cs - Common/DTS.Common.IConnection/USBConnection/WINUSBConnection/CDCUSBConnection.cs - Common/DTS.Common.IConnection/USBConnection/WINUSBConnection/WINUSBConnection.cs generated_at: "2026-04-16T11:50:38.580755+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "2043cd8e3c0f04ef" --- # Documentation: DTS.Common.WINUSBConnection ## 1. Purpose This module provides USB connectivity abstractions within the `DTS.Common.WINUSBConnection` namespace. It contains two concrete implementations of the `IConnection` interface: `CDCUSBConnection`, which wraps a standard `System.IO.Ports.SerialPort` for CDC (Communications Device Class) USB devices, and `WINUSBConnection`, which provides low-level communication via the native `winusb.dll` API for custom WinUSB devices. Additionally, it defines the internal P/Invoke signatures and data structures required to interact with the Windows WinUSB driver stack. ## 2. Public Interface ### Class: `CDCUSBConnection` Implements `IConnection`. Represents a USB device connection via a virtual COM port (CDC). * **`void Create(string connectString, string hostIPAddress)`** * Parses the `connectString` to match against registry keys in `RegKeys`. If a match is found, it retrieves the `PortName` from the registry (`Device Parameters` subkey) and configures the internal `SerialPort` instance. * **`IAsyncResult BeginConnect(AsyncCallback cb, object state)`** * Initiates an asynchronous connection. Queues the connection logic to the thread pool. * **`void EndConnect(IAsyncResult ar)`** * Completes the asynchronous connection. Configures the serial port (BaudRate, DataBits, etc.) and calls `_comPort.Open()`. Sets `Connected` to `true`. * **`IAsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncCallback cb, object state)`** * Initiates an asynchronous send operation. * **`int EndSend(IAsyncResult ar)`** * Completes the send operation. Writes data to the internal `_comPort` using `_comPort.Write`. * **`Task SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)`** * Task-based asynchronous wrapper for `BeginSend`/`EndSend`. * **`IAsyncResult BeginReceive(byte[] buffer, int offset, int size, AsyncCallback cb, object state)`** * Initiates an asynchronous receive operation. * **`int EndReceive(IAsyncResult ar)`** * Completes the receive operation. Reads data from `_comPort`. **Note:** This method blocks in a loop (`Thread.Sleep(1)`) until at least one byte is read. * **`IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback cb, Object state)`** * Initiates an asynchronous disconnect. * **`void EndDisconnect(IAsyncResult ar)`** * Completes the disconnect. Closes and disposes the internal `_comPort`. * **Properties** * `bool Connected`: Gets the current connection state. * `string ConnectString`: Returns the device pathname. * `IList RegKeys`: Static property that lazily loads registry keys for the device from `SYSTEM\CurrentControlSet\Enum\USB\`. ### Class: `WINUSBConnection` Implements `IConnection`. Represents a USB device connection using the native WinUSB driver. * **`void Create(string connectString, string hostIPAddress)`** * Stores the `connectString` in the `ConnectString` property. * **`IAsyncResult BeginConnect(AsyncCallback cb, object state)`** * Initiates an asynchronous connection. Throws `NotConnectedException` if already connected. * **`void EndConnect(IAsyncResult ar)`** * Completes the connection. Instantiates a new `WinUsbDevice`, retrieves a device handle via `GetDeviceHandle`, and initializes the device via `InitializeDevice`. Uses a mutex (`_usbConnectionMutex`) to synchronize access. * **`IAsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncCallback cb, object state)`** * Initiates an asynchronous send. Validates buffer parameters. * **`int EndSend(IAsyncResult ar)`** * Completes the send. Checks `MyDevInfo.UseHybridBulkIntMode`. If true, calls `SendViaInterruptTransfer`; otherwise, calls `SendViaBulkTransfer`. * **`Task SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)`** * Task-based asynchronous wrapper for `BeginSend`/`EndSend`. * **`IAsyncResult BeginReceive(byte[] buffer, int offset, int size, AsyncCallback cb, object state)`** * Initiates an asynchronous receive. * **`int EndReceive(IAsyncResult ar)`** * Completes the receive. Reads data via `ReadViaBulkTransfer`. Blocks in a loop (`Thread.Sleep(1)`) until bytes are read. Returns 0 if the connection fails or closes. * **`IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback cb, Object state)`** * Initiates an asynchronous disconnect. * **`void EndDisconnect(IAsyncResult ar)`** * Completes the disconnect. Calls `DisposeSliceDev` to release the WinUSB handle. * **Properties** * `bool Connected`: Gets the current connection state. * `string ConnectString`: Gets the device pathname. ### Internal Class: `WinUsbDevice` (Partial) Defines P/Invoke signatures and structures for `winusb.dll`. * **Structs**: `USBConfigurationDescriptor`, `USBInterfaceDescriptor`, `WinUSBPipeInformation`, `WinUSBSetupPacket`. * **Enums**: `PolicyType`, `USBDPipeTypes`, `USBDeviceSpeeds`. * **Methods**: `WinUsb_Initialize`, `WinUsb_Free`, `WinUsb_ControlTransfer`, `WinUsb_ReadPipe`, `WinUsb_WritePipe`, `WinUsb_QueryPipe`, `WinUsb_SetPipePolicy`, etc. ## 3. Invariants * **Registry Dependency (CDCUSBConnection)**: The `CDCUSBConnection` requires the device to be registered under `SYSTEM\CurrentControlSet\Enum\USB\` with a Vendor ID of `VID_1CB9` and Product ID of `PID_001A`. The `Create` method cannot resolve the port name if these registry keys are missing. * **Thread Safety (WINUSBConnection)**: The `WINUSBConnection.EndConnect` and `DisposeSliceDev` methods rely on a named Mutex (`"USBConnection"`) to prevent race conditions during device initialization and disposal. * **Disposal State**: Both connection classes track `Disposed` and `Disposing` flags. Methods generally do not proceed if `Disposed` is true. * **APM Pattern**: Both classes implement the Asynchronous Programming Model (APM) using internal `IAsyncResult` implementations (`UsbRecAsyncResult` and `WinUSBRecAsyncResult`). Callbacks are invoked via `ThreadPool.QueueUserWorkItem`. ## 4. Dependencies ### Internal Dependencies * `DTS.Common.Interface.Connection`: Implements `IConnection`. * `DTS.Common.DASResource`: Uses localized strings for exception messages (e.g., `Strings.CDCUSBConnection_BeginConnect_Err1`). * `DTS.Common.Utilities.Logging`: Uses `APILogger` for logging exceptions and status messages. * `DTS.Common.USBFramework`: Uses `DeviceManagement` class (in `WINUSBConnection`). * `DTS.Common.Classes.Connection`: Uses `NotConnectedException`. ### External Dependencies * `System.IO.Ports`: Used by `CDCUSBConnection` for `SerialPort`. * `System.Runtime.InteropServices`: Used for P/Invoke attributes. * `Microsoft.Win32`: Used for registry access (`RegistryKey`, `SafeFileHandle`). * `winusb.dll`: Native Windows DLL imported by `WinUsbDevice`. ## 5. Gotchas * **Blocking Async Reads**: The `EndReceive` methods in both `CDCUSBConnection` and `WINUSBConnection` contain `while` loops that sleep (`Thread.Sleep(1)`) if zero bytes are read. This effectively makes the "asynchronous" operation blocking and consumes a thread pool thread while waiting for data. * **Recursive Comment**: The `Create(string connectString)` method in both connection classes contains a commented-out line `//Create(connectString);` with a note "this is recursive!". This suggests a historical bug or confusion regarding method overloads. * **Empty Soft Disconnect**: `SoftConnect` and `SoftDisconnect` methods are implemented but empty. The comments explicitly state they do nothing because there is no soft disconnect option implemented. * **Hardcoded Device IDs**: `CDCUSBConnection` hardcodes `DTS_VENDOR_ID` (0x1CB9) and `DTS_TSR2_CDCUSB_PRODUCT_ID_STR` ("PID_001A"). It will not work with other USB devices. * **Partial Class Source**: `WinUsbDevice` is defined as `internal sealed partial class`. The logic for `GetDeviceHandle`, `InitializeDevice`, `SendViaBulkTransfer`, etc., is referenced in `WINUSBConnection` but is **not present in the provided source files** (likely in another file part of the partial class definition). * **Hybrid Mode Logic**: `WINUSBConnection.EndSend` switches between interrupt and bulk transfers based on a boolean `UseHybridBulkIntMode` located on a `MyDevInfo` object. The definition of `MyDevInfo` is not visible in the provided source.