Files
DP44/enriched-qwen3-coder-next/DataPRO/DASFactory.md
2026-04-17 14:55:32 -04:00

12 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/DASFactory/DASFactory.AutoDiscovery.cs
DataPRO/DASFactory/DASFactory.WinUSB.cs
DataPRO/DASFactory/DASFactory.CDCUSB.cs
DataPRO/DASFactory/DASFactory.Ribeye.cs
DataPRO/DASFactory/DASFactory.WindowsNotification.cs
DataPRO/DASFactory/DistributorSocket.cs
DataPRO/DASFactory/DASFactory.HID.cs
2026-04-16T03:50:36.719547+00:00 Qwen/Qwen3-Coder-Next-FP8 1 440f548bb3fa7458

DASFactory

Documentation Page: DASFactory Device Discovery and Handling Module


1. Purpose

This module implements device discovery and lifecycle management for multiple hardware interface types (UDP multicast, HID, WinUSB, CDCUSB, and Ethernet-based Ribeye) within the DAS (Data Acquisition System) factory framework. It enables background scanning for UDP-based devices via multicast, real-time detection of USB/HID device insertion/removal via Windows notifications, and structured connection/disconnection workflows for each device type. The module serves as the core infrastructure for dynamically managing connected DAS devices in the system, ensuring devices are correctly identified, validated, and integrated into the broader DAS ecosystem.


2. Public Interface

The module contains no public classes—all classes (AutoDiscovery, WinUSBHandling, CDCUSBHandling, RibeyeHandling, HIDHandling, WindowsNotification, DistributorSocket) are declared internal. Therefore, there is no public surface area exposed by this module.

However, the following internal classes and methods constitute the functional interface used by other internal modules (e.g., DASFactory):

AutoDiscovery

  • void StartMulticastAutoDiscovery()
    Starts a background task that periodically polls for UDP devices via _dasFactory.AutoDiscoverMulticast(...). Uses a CancellationToken for cancellation. Ensures only one scan task runs at a time via _multicastLock.
  • void StopMulticastAutoDiscovery()
    Cancels the active scan task and waits for it to complete. Disposes and recreates the CancellationTokenSource if previously cancelled.
  • IDiscoveredDevice[] GetDiscoveredDevices()
    Returns a snapshot (copy) of all discovered devices since the last StartMulticastAutoDiscovery() call. Thread-safe via _multicastLock.

WinUSBHandling

  • Inherits from WindowsNotification.
  • Overrides NotificationDeviceArrived, NotificationDeviceRemoved.
  • public override void UpdateConnectedDevices()
    Enumerates connected WinUSB devices, checks for duplicates, and connects new ones.
  • public override void UpdateDisconnectedDevices()
    Detects and disconnects devices that are no longer present.
  • public override void UpdateDeviceSetups()
    Sets this as the handler for the associated IDeviceSetup.

CDCUSBHandling

  • Inherits from WindowsNotification.
  • Overrides NotificationDeviceArrived, NotificationDeviceRemoved.
  • public override void UpdateConnectedDevices()
    Enumerates CDCUSB devices (filtered by registry keys in GetListOfConnectedDevices()), checks for duplicates, and connects new ones.
  • public override void UpdateDisconnectedDevices()
    Detects and disconnects removed CDCUSB devices.
  • public override void UpdateDeviceSetups()
    Sets this as the handler for the associated IDeviceSetup.

RibeyeHandling

  • Implements IDeviceSetup.
  • bool QueryInformation(ConnectedDevice dev)
    Queries device metadata (serial number, LED count, firmware, supported modes/rates) via protocol commands (QueryArmAndTriggerStatus, QuerySerialNumber, QueryNumberOfLEDs). On failure, sets dev.InUpdateMode = true.
  • ICommunication GetICommunication() / GetICommunication(ConnectedDevice dev)
    Returns EthernetRibeye instances.
  • IConnectedDevice GetIConnectedDevice(ICommunication comm)
    Wraps EthernetRibeye in ConnectedEthernetRibeye.
  • bool IsCorrectType(ConnectedDevice dev)
    Returns true if dev.Dev is ConnectedEthernetRibeye.
  • DASType GetDASType()ETHERNET_RIBEYE
  • Guid GetGuid()Guid.Empty
  • int GetProductId() / string GetProductIdString()0 / string.Empty
  • void SetHandler(DeviceHandling handler) → no-op.

WindowsNotification

  • Abstract base class for device notification handlers.
  • Constructor registers for Windows device notifications via DeviceManagement.RegisterForDeviceNotifications(...).
  • protected abstract void NotificationDeviceArrived(ref Message m)
    Called on device arrival (via NotificationWndProc).
  • protected abstract void NotificationDeviceRemoved(ref Message m)
    Called on device removal.
  • protected virtual void NotificationWndProc(ref Message m)
    Filters WM_DEVICECHANGE messages for DBT_DEVICEARRIVAL / DBT_DEVICEREMOVECOMPLETE, dispatching to abstract handlers.

DistributorSocket

  • public bool IsConnected()
    Returns true if _sock is non-null and connected.
  • public void Disconnect()
    Shuts down and closes the socket, disposes resources.
  • public bool ReadLine(ref string target, ref bool stopFlag)
    Reads a line from _reader with retry logic (up to MAX_CONSECUTIVE_READ_ERRORS = 2). Logs each message.
  • public void SendAck() / SendNak()
    Sends "ACK" or "NAK" over _writer, with logging and error handling.
  • public bool KeepAliveEnabled()
    Sends a keep-alive configuration string (<...>) to the remote endpoint and waits for a response. Sets _keepAliveEnabled = true on success.
  • public void Dispose()
    Closes and disposes the socket.

3. Invariants

  • AutoDiscovery

    • _scanTask is null or completed only when no scan is running.
    • _scanTask is never started if already running (lock + null/completed check).
    • _discoveredDevices list is append-only: existing entries are never updated or removed during discovery; only new devices (by unique Serial) are added.
    • ClearDiscoveredDevices() is called at the start of each DiscoveryWork iteration.
    • Cancellation token is not reusable; once cancelled, a new CancellationTokenSource is created.
  • WinUSBHandling, CDCUSBHandling, HIDHandling

    • Device path lists are deduplicated (case-insensitive) before use.
    • CheckForConnectedWinUSBDups() / CheckForConnectedCDCUSBDups() throw if duplicate device paths are detected.
    • GetListOfConnectedDevices() returns a list of device paths; for CDCUSB, paths must contain at least one registry key from CDCUSBConnection.RegKeys (case-insensitive substring match).
    • ConnectWinUSBTimeout / ConnectCDCUSBTimeout / ConnectHIDTimeout are set to 60000, 60000, and 1000 ms respectively.
  • RibeyeHandling

    • Samplerate2AAFilterDict is immutable and pre-populated with 9 sample rates (500100000 Hz), each mapped to sampleRate / 5.0F.
    • QueryInformation may silently retry QueryArmAndTriggerStatus on first boot (CRC initialization issue).
    • Module serial numbers are derived as <DAS serial>-<Index>; firmware versions default to "0000".
  • WindowsNotification

    • A hidden NotificationForm is created and shown (then hidden) to receive Windows messages.
    • Device notification registration is mandatory; failure throws an exception.
    • RecipientHandle and DeviceNotifyHandle are initialized in the constructor.
  • DistributorSocket

    • TCP keep-alive is enabled and configured via IOControlCode.KeepAliveValues.
    • Connection retry loop respects slicedbCanConnect, whKillMe, and _bShutDownByNow flags.
    • ReadLine fails if stopFlag is true or MAX_CONSECUTIVE_READ_ERRORS is exceeded.

4. Dependencies

Internal Dependencies (from source):

  • DTS.Common.* namespaces:
    • DTS.Common.Enums.DASFactory (DFConstantsAndEnums, MultiCastDeviceClasses)
    • DTS.Common.Interface.DASFactory (IDASFactory, IDiscoveredDevice, IDeviceSetup)
    • DTS.Common.DASResource, DTS.Common.DAS.Concepts, DTS.Common.ICommunication, DTS.Common.Utilities.Logging, DTS.Common.WINUSBConnection, DTS.Common.USBFramework
  • DTS.DASLib.* namespaces:
    • DTS.DASLib.Command.* (e.g., Ribeye commands: QueryArmAndTriggerStatus, QuerySerialNumber, QueryNumberOfLEDs)
    • DTS.DASLib.Connection.*, DTS.DASLib.Communication, DTS.DASLib.Service
  • System namespaces:
    • System.Collections.Concurrent, System.Threading, System.Windows.Forms, System.Net.Sockets, System.Runtime.InteropServices

External Dependencies:

  • Windows API (via DeviceManagement, FileIODeclarations, HIDeclarations) for device enumeration and HID access.
  • MyDeviceManagement.FindDeviceFromGuid(...) (from DTS.Common.USBFramework) for device path enumeration.
  • CDCUSBConnection.RegKeys (from DTS.Common.WINUSBConnection) for CDCUSB path filtering.

Inferred Usage:

  • AutoDiscovery is used by DASFactory (via _dasFactory field) to enable multicast discovery.
  • WinUSBHandling, CDCUSBHandling, HIDHandling, RibeyeHandling are instantiated and wired into DASFactory for their respective device types.
  • DistributorSocket is used for remote communication (e.g., with a "slice db" server), likely in distributed acquisition scenarios.

5. Gotchas

  • AutoDiscovery

    • Cancellation is not idempotent: once tokenSource.Cancel() is called, tokenSource is disposed and a new one is created. Reusing the same instance after cancellation is impossible.
    • DiscoveryWork always clears _discoveredDevices at the start of each loop iteration, meaning only devices discovered in the current scan cycle are retained (unless StartMulticastAutoDiscovery is called again).
    • GetDiscoveredDevices() returns a copy (ToArray()), but the internal list is not versioned—concurrent UpdateDevices calls may overwrite each others additions if not for the lock.
  • WinUSBHandling, CDCUSBHandling, HIDHandling

    • Device path deduplication uses string.IsNullOrEmpty(t) and case-insensitive Equals, but GetAllHIDDevices() and GetListOfConnectedDevices() may return null on failure (not an empty list), which downstream code must handle.
    • HIDHandling.ReadRegKeys() silently clears RegKeys on exception; if registry access fails, no devices will match in NotificationDeviceArrived.
    • In HIDHandling.NotificationDeviceArrived, if RegKeys is empty (e.g., due to registry error), the device is ignored—even if its valid—until ReadRegKeys() is called again (e.g., on next arrival).
    • WinUSBHandling and CDCUSBHandling both call CheckForConnected...Dups() and throw if duplicates are found—this is a hard failure, not a warning.
  • RibeyeHandling

    • QueryInformation may fail silently on first boot (CRC issue), but only retries once. If the second attempt fails, QueryInformation returns false and sets dev.InUpdateMode = true.
    • Samplerate2AAFilterDict is shared across all instances (static), but only 9 sample rates are supported. Using unsupported rates will cause a KeyNotFoundException if accessed.
    • GetGuid() returns Guid.Empty, implying this device type may not use GUID-based enumeration (unlike WinUSB/CDCUSB/HID).
  • WindowsNotification

    • NotificationForm is created on the main thread; accessing it from other threads (e.g., in Dispose) is unsafe and commented-out code warns about cross-thread violations.
    • Device notification registration failure throws immediately in the constructor—no fallback.
  • DistributorSocket

    • KeepAliveEnabled() sends a configuration string but does not verify the remote response beyond reading a non-empty line. It does not parse <ACK> (commented out).
    • ReadLine may return an empty string if stopFlag is set or errors exceed threshold—callers must check the return value.
    • SLICE_DB_PORT = 8200 is hardcoded; no configuration support.
  • General

    • All timeout values (ConnectWinUSBTimeout, etc.) are hardcoded in constructors and not configurable at runtime.
    • Logging uses APILogger.LogString(...) and APILogger.Log(...), but no structured error codes—debugging relies on log parsing.
    • No unit tests or validation for IDeviceSetup implementations beyond type checks (IsCorrectType).