Files
DP44/DataPRO/DASFactory/DASFactory.HID.cs
2026-04-17 14:55:32 -04:00

425 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using DTS.DASLib.Connection;
using DTS.DASLib.Service;
using DTS.DASLib.Connection.USBFramework;
using DTS.DASLib.Communication;
using DTS.DASLib.Command.SLICE;
using DTS.DASLib.Command;
using DTS.DASLib.DASResource;
using DTS.DAS.Concepts;
namespace DTS.DASLib.DASFactory
{
internal class HIDHandling: WindowsNotification
{
/// <summary>
/// Timeout in milliseconds to connect an HID device
/// </summary>
public int ConnectHIDTimeout { get; set; }
private IDeviceSetup deviceHandler { get; set; }
#region Registry handling
protected List<String> RegKeys = new List<string>();
protected void ReadRegKeys()
{
try
{
RegKeys.Clear();
ReadHIDRegKeys();
}
catch(System.Exception)
{
// we don't care what is was, an empty list is fine
}
}
protected void ReadHIDRegKeys()
{
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_1CB9&PID_0003\6&29dd55fe&0&0000
//RegKeys.Clear();
var ourKey = Microsoft.Win32.Registry.LocalMachine;
var ourName = @"SYSTEM\CurrentControlSet\Enum\HID\" + DTS_VENDOR_ID_STR + "&" + deviceHandler.GetProductIDString();
ourKey = ourKey.OpenSubKey(ourName);
//if ourKey is null, this will throw an exception, but since nothing is done in the current
//exception handler, the old code was just bypassing this code anyhow (when there's an exception)
//6/8/2010 - dtm
if (null != ourKey)
{
foreach (var subKey in ourKey.GetSubKeyNames())
{
RegKeys.Add(subKey);
}
}
}
#endregion
public HIDHandling(DASFactory _factory, UpdateFinishedEventHandler _SerialUpdateFinished, IDeviceSetup _deviceHandler)
: base(_factory, _SerialUpdateFinished, _deviceHandler.GetGuid())
{
deviceHandler = _deviceHandler;
ReadRegKeys();
ConnectHIDTimeout = 1000; // 1000 ms
}
#region HID WinProc's
protected override void NotificationDeviceArrived(ref System.Windows.Forms.Message m)
{
try
{
DTS.Utilities.Logging.APILogger.LogString("HIDArrived: A device has been connected");
// this can either be a HEADS or a SLICE device being connected
// \\?\hid#vid_1cb9&pid_0002#6&29dd55fe&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
var bcdi = (DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(m.LParam, typeof(DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE));
var devNameArr = bcdi.dbcc_name.Split('#');
var foundKey = RegKeys.Find(delegate(String ss) { return ss == devNameArr[2]; });
if(foundKey != null)
{
SerialUpdateActionQueue.EnqueueConnect();
}
else
{
ReadRegKeys();
}
}
catch(System.Exception ex)
{
DTS.Utilities.Logging.APILogger.LogString("HIDArrived caught an exception: " + ex.Message + " " + ex.StackTrace);
MessageBox.Show("HIDArrived caught an exception: " + ex.Message + " " + ex.StackTrace, "Error");
}
finally
{
DTS.Utilities.Logging.APILogger.LogString("HIDArrived: Exit");
}
}
protected override void NotificationDeviceRemoved(ref System.Windows.Forms.Message m)
{
try
{
DTS.Utilities.Logging.APILogger.LogString("HIDRemoved: A device has been disconnected");
//var bcdi2 = (DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(m.LParam, typeof(DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE));
SerialUpdateActionQueue.EnqueueDisconnect();
}
catch(System.Exception ex)
{
DTS.Utilities.Logging.APILogger.LogString("HIDRemoved caught an exception: " + ex.Message + " " + ex.StackTrace);
MessageBox.Show("HIDRemoved caught an exception: " + ex.Message + " " + ex.StackTrace, "Error");
}
finally
{
DTS.Utilities.Logging.APILogger.LogString("HIDRemoved: Exit");
}
}
#endregion
protected override void UpdateDisconnectedDevices()
{
ConnectNewDevices(new GetDeviceStrings(delegate() { return GetListOfConnectedHIDDevices(); }),
new GetDeviceStrings(delegate() { return GetConnectedStrings(); }),
new GetICommunication(delegate() { return deviceHandler.GetICommunication(); }),
new GetIConnectedDevice(delegate(ICommunication comm) { return deviceHandler.GetIConnectedDevice(comm); }),
deviceHandler.GetDASType(),
deviceHandler,
ConnectHIDTimeout);
}
protected override void UpdateConnectedDevices()
{
DisconnectRemovedDevices(new GetDeviceStrings(delegate()
{
return GetListOfConnectedHIDDevices();
}),
new DASTypeFilter(delegate(ConnectedDevice dev)
{
return deviceHandler.IsCorrectType(dev);
}),
new ConnectedDevice2Communication(delegate(ConnectedDevice dev)
{
return deviceHandler.GetICommunication(dev);
}),
deviceHandler.GetDASType(),
ConnectHIDTimeout);
}
#region Connection functions
private List<string> GetAllHIDDevices()
{
string[] AllHIDDevicePathNames = new string[128];
try
{
// Fill an array with the device path names of all attached HIDs.
if(!MyDeviceManagement.FindDeviceFromGuid(deviceHandler.GetGuid(), ref AllHIDDevicePathNames))
{
return null;
}
}
catch
{
return null;
}
// loop thru the array and copy the new ones (that actually contain something)
// over to the list newNames
List<string> newNames = new List<string>();
for(int i = 0; i < AllHIDDevicePathNames.Length; i++)
{
if(string.IsNullOrEmpty(AllHIDDevicePathNames[i]))
continue;
// protect against windows giving us more than one of the same
if(newNames.Find(delegate(String str) { return str.Equals(AllHIDDevicePathNames[i], StringComparison.OrdinalIgnoreCase); }) == null)
{
// no, we haven't added it yet so do it now
newNames.Add(AllHIDDevicePathNames[i]);
}
}
return newNames;
}
private int OpenDevicePath(string devicePath)
{
int devHandle;
try
{
devHandle = FileIODeclarations.CreateFile(devicePath,
0,
FileIODeclarations.FILE_SHARE_READ | FileIODeclarations.FILE_SHARE_WRITE,
ref Security,
FileIODeclarations.OPEN_EXISTING,
0,
0);
}
catch
{
return FileIODeclarations.INVALID_HANDLE_VALUE;
}
return devHandle;
}
private List<string> FilterHIDDeviceList(List<string> newNames, int vid, int pid)
{
if(newNames == null || newNames.Count == 0)
{
return null;
}
// now we have a list of new unique devices, make a new list containing only the ones that are of the right type
List<string> newRecorderNames = new List<string>();
foreach(string devicePath in newNames)
{
try
{
int devHandle = OpenDevicePath(devicePath);
if(devHandle == FileIODeclarations.INVALID_HANDLE_VALUE)
{
continue;
}
HIDevice deviceHID = new HIDevice();
// Set the Size property of DeviceAttributes to the number of bytes in the structure.
deviceHID.DeviceAttributes.Size = Marshal.SizeOf(deviceHID.DeviceAttributes);
int Result = HIDDeclarations.HidD_GetAttributes(devHandle, ref deviceHID.DeviceAttributes);
if(Result == 0)
{
// There was a problem in retrieving the information.
FileIODeclarations.CloseHandle(devHandle);
continue;
}
// Find out if the device matches the one we're looking for.
if(deviceHID.DeviceAttributes.VendorID != vid ||
deviceHID.DeviceAttributes.ProductID != pid)
{
// It's not a match, so close the handle.
FileIODeclarations.CloseHandle(devHandle);
continue;
}
// we don't need this handle anymore
FileIODeclarations.CloseHandle(devHandle);
// it's a new one
newRecorderNames.Add(devicePath);
}
catch
{
// ignore it, try the next one
}
}
return newRecorderNames;
}
private List<string> GetListOfConnectedHIDDevices()
{
var newNames = GetAllHIDDevices();
if(newNames == null || newNames.Count == 0)
{
return null;
}
// now we have a list of new unique devices, make a new list containing only the ones that are of the right type
List<string> newRecorderNames;
try
{
newRecorderNames = FilterHIDDeviceList(newNames, DTS_VENDOR_ID, deviceHandler.GetProductID());
}
catch
{
return null;
}
return newRecorderNames;
}
#endregion
/*
#region HID update (not updated yet to separate callbacks)
private bool UpdateConnectedHID()
{
bool devicesFound = false;
try
{
DTS.Utilities.Logging.APILogger.LogString("UpdateConnectedHID: Enter");
// get a list of SLICE units currently connected thru HID
var ConnectedHIDSlices = GetListOfConnectedHIDSlices();
devicesFound = (null != ConnectedHIDSlices && ConnectedHIDSlices.Count > 0);
if(devicesFound)
{
// subtract the ones we already know about
var NewHIDSlices = ConnectedHIDSlices.Except(GetConnectedStrings());
// add the new ones
foreach(var devPath in NewHIDSlices)
{
var newHIDSlice = new HIDUSBSlice();
var newConnectedHIDSlice = new ConnectedHIDSlice(newHIDSlice);
// try to connect it
newHIDSlice.Connect(devPath,
ConnectHIDCallback,
new DeviceAndWaitTuple(newConnectedHIDSlice, null),
ConnectHIDTimeout);
}
// now see if we have to remove any
IEnumerable<ConnectedDevice> DevicesToRemove;
lock(ConnectedDevicesLock)
{
DevicesToRemove = from dev in ConnectedDevices
where !ConnectedHIDSlices.Contains(dev.dev.ConnectString)
select dev;
}
// each one in this list must be disconnected
foreach(var dev in DevicesToRemove)
{
// this is one of those places where we need to get to the ICommunication part
((dev.dev as IConnectedDAS).Comm as ICommunication).Disconnect(false,
ConnectHIDCallback,
new DeviceAndWaitTuple(dev, null),
ConnectHIDTimeout);
}
}
return devicesFound;
}
catch(System.Exception ex)
{
DTS.Utilities.Logging.APILogger.LogString(string.Format("DASFactory.UpdateConnectedHID: Exception {0} at {1}", ex.Message, ex.StackTrace));
MessageBox.Show(string.Format("DASFactory.UpdateConnectedHID: Exception {0} at {1}", ex.Message, ex.StackTrace));
return false;
}
finally
{
DTS.Utilities.Logging.APILogger.LogString("UpdateConnectedWinUSB: Exit");
}
return devicesFound;
}
// this is our callback for both connect and disconnect
private bool ConnectHIDCallback(ICommunicationReport report)
{
Debug.Assert(report.UserState is DeviceAndWaitTuple);
var DeviceParameter = (report.UserState as DeviceAndWaitTuple).Device;
var newHidUSB = DeviceParameter as ConnectedDevice;
ConnectedDevice newDev;
if(null != newHidUSB)
{
newDev = newHidUSB;
}
else
{
newDev = new ConnectedDevice();
newDev.dev = DeviceParameter as IConnectedDevice;
newDev.dastype = ConnectedDevice.DASType.HID_SLICE;
// assume not in update mode
newDev.InUpdateMode = false;
}
if(report.Result == CommunicationResult.ConnectOK)
{
// fill the DASInfo
var SliceInfoOK = sliceHandler.QueryInformation(newDev);
// add it to our list
lock(ConnectedDevicesLock)
{
ConnectedDevices.Add(newDev);
}
// notify our subscribers
if(!SliceInfoOK)
{
factory.ReportFailed();
}
else
{
factory.ReportArrived();
}
}
else if(report.Result == CommunicationResult.DisconnectOK)
{
// first dispose of it
newDev.Dispose();
// remove it from our list
lock(ConnectedDevicesLock)
{
ConnectedDevices.Remove(newDev);
}
// notify our subscribers
factory.ReportRemoved();
}
else
{
// first dispose of it
newDev.Dispose();
factory.ReportFailed();
}
return true;
}
#endregion
*/
}
}