Skip to content

Commit

Permalink
RELEASE 2.1.0 (May 4, 2019)
Browse files Browse the repository at this point in the history
Added experimental Bluetooth Low Energy support on Windows. This part of the library may change in the future. Let me know how it works for you.
Fixed a race condition in the exclusivity layer.
Fixed a threading bug that cropped up on .NET Core on Linux.
Serial devices that use Windows's buggy usbser.sys driver are now compatible with HIDSharp, including the detection of connection and disconnection.

Signed-off-by: James F. Bellinger <http://www.zer7.com/software/hidsharp>
  • Loading branch information
benedekkupper committed Jul 30, 2020
1 parent 57553f0 commit 87ad1d3
Show file tree
Hide file tree
Showing 59 changed files with 3,689 additions and 308 deletions.
133 changes: 132 additions & 1 deletion HidSharp.Test/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ under the License. */
using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using HidSharp.Experimental;
using HidSharp.Reports;
using HidSharp.Reports.Encodings;
using HidSharp.Utility;

namespace HidSharp.Test
{
Expand Down Expand Up @@ -65,9 +68,137 @@ static void WriteDeviceItemInputParserResult(Reports.Input.DeviceItemInputParser

static void Main(string[] args)
{
//Trace.Listeners.Clear();
//Trace.Listeners.Add(new ConsoleTraceListener());

HidSharpDiagnostics.EnableTracing = true;
HidSharpDiagnostics.PerformStrictChecks = true;

var list = DeviceList.Local;
list.Changed += (sender, e) => Console.WriteLine("Device list changed.");


//Console.WriteLine("Beginning discovery.");
//using (list.BeginBleDiscovery())
{

var allDeviceList = list.GetAllDevices().ToArray();
Console.WriteLine("All device list:");
foreach (Device dev in allDeviceList)
{
Console.WriteLine(dev.ToString() + " @ " + dev.DevicePath);
/*
if (dev is HidDevice)
{
foreach (var serialPort in
(((HidDevice)dev).GetSerialPorts()))
{
Console.WriteLine(" " + serialPort);
}
}
*/
}

var bleDeviceList = list.GetBleDevices().ToArray();
Console.WriteLine("BLE device list:");
foreach (BleDevice dev in bleDeviceList)
{
Console.WriteLine(dev.ToString() + "@" + dev.DevicePath);
foreach (var service in dev.GetServices())
{
Console.WriteLine(string.Format("\tService: {0}", service.Uuid));
foreach (var characteristic in service.GetCharacteristics())
{
Console.WriteLine(string.Format("\t\tCharacteristic: {0} (Properties: {1})", characteristic.Uuid, characteristic.Properties));
foreach (var descriptor in characteristic.GetDescriptors())
{
Console.WriteLine(string.Format("\t\t\tDescriptor: {0}", descriptor.Uuid));
}
}

if (service.Uuid == new BleUuid("63dc0001-fa35-4205-b09f-0fc6072ec515"))
{
try
{
using (var svc = dev.Open(service))
{
Console.WriteLine("Opened!");

BleCharacteristic rx = null;

foreach (var ch in service.GetCharacteristics())
{
Console.WriteLine(string.Format("{0} = {1}", ch.Uuid, ch.IsReadable ? string.Join(" ", svc.ReadCharacteristic(ch)) : "N/A"));

foreach (var d in ch.GetDescriptors())
{
Console.WriteLine(string.Format("\t{0} = {1}", d.Uuid, string.Join(" ", svc.ReadDescriptor(d))));
}

if (BleCccd.Notification != svc.ReadCccd(ch))
{
svc.WriteCccd(ch, BleCccd.Notification);
}

if (ch.Uuid == new BleUuid("63dc0002-fa35-4205-b09f-0fc6072ec515")) { rx = ch; }
}

Action beginReadEvent = null;
AsyncCallback endReadEvent = null;
beginReadEvent = () =>
{
svc.BeginReadEvent(endReadEvent, null);
};
endReadEvent = ar =>
{
BleEvent @event;
try
{
@event = svc.EndReadEvent(ar);
}
catch (ObjectDisposedException)
{
Console.WriteLine("closed");
return;
}
catch (TimeoutException)
{
Console.WriteLine("timed out");
@event = default(BleEvent);
}
if (@event.Value != null)
{
Console.WriteLine(string.Format("{0} -> {1}", @event.Characteristic, string.Join(" ", @event.Value.Select(x => x.ToString()))));
if (rx != null)
{
Console.WriteLine("writing");
svc.WriteCharacteristicWithoutResponse(rx, new[] { (byte)0xdd, (byte)1, (byte)'A' });
}
}
beginReadEvent();
};
beginReadEvent();

Thread.Sleep(30000);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}

Console.WriteLine();
Console.WriteLine("Press any key");
Console.ReadKey();
Console.WriteLine();
}
//Console.WriteLine("Ending discovery.");

/*
var serialDeviceList = list.GetSerialDevices().ToArray();
Console.WriteLine("Serial device list:");
Expand Down
6 changes: 6 additions & 0 deletions HidSharp/AsyncResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ internal T EndOperation()
}
}

internal static T EndOperation(IAsyncResult asyncResult)
{
Throw.If.Null(asyncResult);
return ((AsyncResult<T>)asyncResult).EndOperation();
}

public AsyncCallback AsyncCallback
{
get;
Expand Down
29 changes: 29 additions & 0 deletions HidSharp/CommonException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#region License
/* Copyright 2019 James F. Bellinger <http://www.zer7.com/software/hidsharp>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
#endregion

using System;

namespace HidSharp
{
static class CommonException
{
public static ObjectDisposedException CreateClosedException()
{
return new ObjectDisposedException("Closed.", (Exception)null);
}
}
}
12 changes: 10 additions & 2 deletions HidSharp/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ under the License. */

using System;
using System.Diagnostics;
using HidSharp.Utility;

namespace HidSharp
{
Expand All @@ -43,7 +44,8 @@ protected virtual DeviceStream OpenDeviceAndRestrictAccess(OpenConfiguration ope
DeviceOpenUtility openUtility = null;
if (exclusive)
{
openUtility = new DeviceOpenUtility(this, openConfig);
string streamPath = GetStreamPath(openConfig);
openUtility = new DeviceOpenUtility(this, streamPath, openConfig);
openUtility.Open();
}

Expand All @@ -57,7 +59,7 @@ protected virtual DeviceStream OpenDeviceAndRestrictAccess(OpenConfiguration ope
openUtility.InterruptRequested += (sender, e) =>
{
stream.OnInterruptRequested();
Debug.WriteLine("** HIDSharp delivered an interrupt request.");
HidSharpDiagnostics.Trace("Delivered an interrupt request.");
};
}
}
Expand All @@ -72,6 +74,12 @@ protected virtual DeviceStream OpenDeviceAndRestrictAccess(OpenConfiguration ope

protected abstract DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig);

// Used for exclusion... and also may be used inside OpenDeviceDirectly if desired.
protected virtual string GetStreamPath(OpenConfiguration openConfig)
{
return DevicePath;
}

/// <summary>
/// Tries to make a connection to the device.
/// </summary>
Expand Down
42 changes: 37 additions & 5 deletions HidSharp/DeviceList.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#region License
/* Copyright 2015-2016, 2018 James F. Bellinger <http://www.zer7.com/software/hidsharp>
/* Copyright 2015-2016, 2018-2019 James F. Bellinger <http://www.zer7.com/software/hidsharp>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@ under the License. */
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using HidSharp.Experimental;

namespace HidSharp
{
Expand Down Expand Up @@ -51,13 +52,44 @@ protected DeviceList()

}

/*
public abstract BleDiscovery BeginBleDiscovery();
*/

public virtual IEnumerable<Device> GetDevices(DeviceTypes types)
{
// Improve performance by implementing this override.
return GetAllDevices().Where(device =>
{
if (device is HidDevice && 0 != (types & DeviceTypes.Hid)) { return true; }
if (device is SerialDevice && 0 != (types & DeviceTypes.Serial)) { return true; }
if (device is BleDevice && 0 != (types & DeviceTypes.Ble)) { return true; }
return false;
});
}

public IEnumerable<Device> GetDevices(DeviceTypes types, DeviceFilter filter)
{
Throw.If.Null(filter, "filter");
return GetDevices(types).Where(device => filter(device));
}

/// <summary>
/// Gets a list of all connected BLE devices.
/// </summary>
/// <returns>The device list.</returns>
public IEnumerable<BleDevice> GetBleDevices()
{
return GetDevices(DeviceTypes.Ble).Cast<BleDevice>();
}

/// <summary>
/// Gets a list of all connected HID devices.
/// </summary>
/// <returns>The device list.</returns>
public IEnumerable<HidDevice> GetHidDevices()
{
return GetAllDevices().OfType<HidDevice>();
return GetDevices(DeviceTypes.Hid).Cast<HidDevice>();
}

/// <summary>
Expand All @@ -70,7 +102,7 @@ public IEnumerable<HidDevice> GetHidDevices()
/// <returns>The filtered device list.</returns>
public IEnumerable<HidDevice> GetHidDevices(int? vendorID = null, int? productID = null, int? releaseNumberBcd = null, string serialNumber = null)
{
return GetAllDevices(d => DeviceFilterHelper.MatchHidDevices(d, vendorID, productID, releaseNumberBcd, serialNumber)).Cast<HidDevice>();
return GetDevices(DeviceTypes.Hid, d => DeviceFilterHelper.MatchHidDevices(d, vendorID, productID, releaseNumberBcd, serialNumber)).Cast<HidDevice>();
}

/// <summary>
Expand All @@ -79,11 +111,11 @@ public IEnumerable<HidDevice> GetHidDevices(int? vendorID = null, int? productID
/// <returns>The device list.</returns>
public IEnumerable<SerialDevice> GetSerialDevices()
{
return GetAllDevices().OfType<SerialDevice>();
return GetDevices(DeviceTypes.Serial).Cast<SerialDevice>();
}

/// <summary>
/// Gets a list of all connected HID and serial devices.
/// Gets a list of all connected HID, BLE, and serial devices.
/// </summary>
/// <returns>The device list.</returns>
public abstract IEnumerable<Device> GetAllDevices();
Expand Down
Loading

0 comments on commit 87ad1d3

Please sign in to comment.