425 lines
17 KiB
C#
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
|
|
*/
|
|
}
|
|
}
|