├── .github └── workflows │ └── dotnet.yml ├── .gitignore ├── HidSharp.NETStandard.sln ├── HidSharp.Test ├── HidSharp.Test.NETStandard.csproj ├── HidSharp.Test.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── app.config ├── HidSharp.sln ├── HidSharp ├── AsyncResult.cs ├── CommonException.cs ├── Device.cs ├── DeviceException.cs ├── DeviceFilter.cs ├── DeviceList.cs ├── DeviceListChangedEventArgs.cs ├── DeviceOpenUtility.cs ├── DeviceStream.cs ├── DeviceTypes.cs ├── Exceptions │ ├── DeviceIOException.cs │ ├── DeviceUnauthorizedAccessException.cs │ └── IDeviceException.cs ├── Experimental │ ├── BleCccd.cs │ ├── BleCharacteristic.cs │ ├── BleCharacteristicProperties.cs │ ├── BleDescriptor.cs │ ├── BleDevice.cs │ ├── BleDiscovery.cs │ ├── BleEvent.cs │ ├── BleRequestFlags.cs │ ├── BleService.cs │ ├── BleStream.cs │ ├── BleUuid.cs │ └── BleUuids.cs ├── FilteredDeviceList.cs ├── HidDevice.cs ├── HidDeviceLoader.cs ├── HidSharp.NETStandard.csproj ├── HidSharp.csproj ├── HidStream.cs ├── ImplementationDetail.cs ├── LocalDeviceList.cs ├── OpenConfiguration.cs ├── OpenOption.cs ├── OpenPriority.cs ├── Platform │ ├── HidManager.cs │ ├── HidSelector.cs │ ├── Libusb │ │ ├── LibusbHidManager.cs │ │ └── NativeMethods.cs │ ├── Linux │ │ ├── LinuxHidDevice.cs │ │ ├── LinuxHidManager.cs │ │ ├── LinuxHidStream.cs │ │ ├── LinuxSerialDevice.cs │ │ ├── LinuxSerialStream.cs │ │ ├── NativeMethods.cs │ │ ├── NativeMethodsLibudev.cs │ │ ├── NativeMethodsLibudev0.cs │ │ └── NativeMethodsLibudev1.cs │ ├── MacOS │ │ ├── MacHidDevice.cs │ │ ├── MacHidManager.cs │ │ ├── MacHidStream.cs │ │ ├── MacSerialDevice.cs │ │ ├── MacSerialStream.cs │ │ └── NativeMethods.cs │ ├── SysBleStream.cs │ ├── SysHidStream.cs │ ├── SysRefCountHelper.cs │ ├── SysSerialStream.cs │ ├── SystemEvents.cs │ ├── Unsupported │ │ └── UnsupportedHidManager.cs │ ├── Utf8Marshaler.cs │ └── Windows │ │ ├── NativeMethods.cs │ │ ├── WinBleCharacteristic.cs │ │ ├── WinBleDescriptor.cs │ │ ├── WinBleDevice.cs │ │ ├── WinBleService.cs │ │ ├── WinBleStream.cs │ │ ├── WinHidDevice.ReportDescriptorBuilder.cs │ │ ├── WinHidDevice.ReportDescriptorReconstructor.cs │ │ ├── WinHidDevice.cs │ │ ├── WinHidManager.cs │ │ ├── WinHidStream.cs │ │ ├── WinSerialDevice.cs │ │ └── WinSerialStream.cs ├── Properties │ └── AssemblyInfo.cs ├── Reports │ ├── DataConvert.cs │ ├── DataItem.cs │ ├── DataItemFlags.cs │ ├── DataValue.cs │ ├── DescriptorCollectionItem.cs │ ├── DescriptorItem.cs │ ├── DeviceItem.cs │ ├── Encodings │ │ ├── CollectionType.cs │ │ ├── EncodedItem.cs │ │ ├── GlobalItemTag.cs │ │ ├── ItemType.cs │ │ ├── LocalItemTag.cs │ │ └── MainItemTag.cs │ ├── ExpectedUsageType.cs │ ├── IndexList.cs │ ├── IndexRange.cs │ ├── Indexes.cs │ ├── Input │ │ ├── DeviceItemInputParser.cs │ │ └── HidDeviceInputReceiver.cs │ ├── Report.cs │ ├── ReportDescriptor.cs │ ├── ReportDescriptorParseState.cs │ ├── ReportType.cs │ ├── Units │ │ ├── CurrentUnit.cs │ │ ├── LengthUnit.cs │ │ ├── LuminousIntensityUnit.cs │ │ ├── MassUnit.cs │ │ ├── TemperatureUnit.cs │ │ ├── TimeUnit.cs │ │ ├── Unit.cs │ │ ├── UnitKind.cs │ │ └── UnitSystem.cs │ └── Usage.cs ├── SerialDevice.cs ├── SerialParity.cs ├── SerialSettings.cs ├── SerialStream.cs ├── Throw.cs └── Utility │ ├── BcdHelper.cs │ ├── HResult.cs │ └── HidSharpDiagnostics.cs ├── License.txt ├── NOTICE.txt └── README.md /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a .NET project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net 3 | 4 | name: .NET 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Setup .NET 20 | uses: actions/setup-dotnet@v4 21 | with: 22 | dotnet-version: 8.0.x 23 | - name: Restore dependencies 24 | run: dotnet restore HidSharp/HidSharp.csproj 25 | - name: Build 26 | run: dotnet build HidSharp/HidSharp.csproj --no-restore 27 | -------------------------------------------------------------------------------- /HidSharp.NETStandard.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2037 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HidSharp", "HidSharp\HidSharp.NETStandard.csproj", "{0DB86674-2A7B-4BDC-93C1-3F7DC771426C}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HidSharp.Test", "HidSharp.Test\HidSharp.Test.NETStandard.csproj", "{5E83ACC1-19FA-4996-BBAE-BF7DB4604812}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /HidSharp.Test/HidSharp.Test.NETStandard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | true 7 | false 8 | HidSharp.Test 9 | HidSharp.Test 10 | ..\bin 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /HidSharp.Test/HidSharp.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | Exe 5 | false 6 | ..\bin\ 7 | Illusory Studios LLC 8 | Copyright © 2010-2013 James F. Bellinger <http://www.zer7.com/software/hidsharp> 9 | HID test program 10 | HidSharp 11 | HidSharp.Test 12 | 1.3.0.0 13 | 1.3.0.0 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /HidSharp.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: ComVisible(false)] 6 | [assembly: Guid("2F0DC374-5974-49E6-A7C6-5FFDEDE5E21D")] 7 | -------------------------------------------------------------------------------- /HidSharp.Test/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /HidSharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HidSharp", "HidSharp\HidSharp.csproj", "{0DB86674-2A7B-4BDC-93C1-3F7DC771426C}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HidSharp.Test", "HidSharp.Test\HidSharp.Test.csproj", "{5E83ACC1-19FA-4996-BBAE-BF7DB4604812}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|Mixed Platforms = Debug|Mixed Platforms 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|Mixed Platforms = Release|Mixed Platforms 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 21 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 22 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Debug|x86.ActiveCfg = Debug|Any CPU 23 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 26 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|Mixed Platforms.Build.0 = Release|Any CPU 27 | {0DB86674-2A7B-4BDC-93C1-3F7DC771426C}.Release|x86.ActiveCfg = Release|Any CPU 28 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 31 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 32 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Debug|x86.ActiveCfg = Debug|Any CPU 33 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 36 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|Mixed Platforms.Build.0 = Release|Any CPU 37 | {5E83ACC1-19FA-4996-BBAE-BF7DB4604812}.Release|x86.ActiveCfg = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | GlobalSection(MonoDevelopProperties) = preSolution 43 | StartupItem = HidSharp.Test\HidSharp.Test.csproj 44 | EndGlobalSection 45 | EndGlobal 46 | -------------------------------------------------------------------------------- /HidSharp/AsyncResult.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Threading; 20 | 21 | namespace HidSharp 22 | { 23 | sealed class AsyncResult : IAsyncResult 24 | { 25 | volatile bool _isCompleted; 26 | ManualResetEvent _waitHandle; 27 | 28 | AsyncResult(AsyncCallback callback, object state) 29 | { 30 | AsyncCallback = callback; AsyncState = state; 31 | } 32 | 33 | void Complete() 34 | { 35 | lock (this) 36 | { 37 | if (_isCompleted) { return; } _isCompleted = true; 38 | if (_waitHandle != null) { _waitHandle.Set(); } 39 | } 40 | 41 | if (AsyncCallback != null) { AsyncCallback(this); } 42 | } 43 | 44 | internal delegate T OperationCallback(); 45 | 46 | internal static IAsyncResult BeginOperation(OperationCallback operation, 47 | AsyncCallback callback, object state) 48 | { 49 | var ar = new AsyncResult(callback, state); 50 | ThreadPool.QueueUserWorkItem(delegate(object self) 51 | { 52 | try { ar.Result = operation(); } 53 | catch (Exception e) { ar.Exception = e; } 54 | ar.Complete(); 55 | }, ar); 56 | return ar; 57 | } 58 | 59 | internal T EndOperation() 60 | { 61 | while (true) 62 | { 63 | if (IsCompleted) 64 | { 65 | if (Exception != null) { throw Exception; } 66 | return Result; 67 | } 68 | AsyncWaitHandle.WaitOne(); 69 | } 70 | } 71 | 72 | internal static T EndOperation(IAsyncResult asyncResult) 73 | { 74 | Throw.If.Null(asyncResult); 75 | return ((AsyncResult)asyncResult).EndOperation(); 76 | } 77 | 78 | public AsyncCallback AsyncCallback 79 | { 80 | get; 81 | private set; 82 | } 83 | 84 | public object AsyncState 85 | { 86 | get; 87 | private set; 88 | } 89 | 90 | public WaitHandle AsyncWaitHandle 91 | { 92 | get 93 | { 94 | lock (this) 95 | { 96 | if (_waitHandle == null) 97 | { 98 | _waitHandle = new ManualResetEvent(_isCompleted); 99 | } 100 | } 101 | 102 | return _waitHandle; 103 | } 104 | } 105 | 106 | public bool CompletedSynchronously 107 | { 108 | get { return false; } 109 | } 110 | 111 | public bool IsCompleted 112 | { 113 | get { return _isCompleted; } 114 | } 115 | 116 | Exception Exception 117 | { 118 | get; 119 | set; 120 | } 121 | 122 | T Result 123 | { 124 | get; 125 | set; 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /HidSharp/CommonException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp 21 | { 22 | static class CommonException 23 | { 24 | public static ObjectDisposedException CreateClosedException() 25 | { 26 | return new ObjectDisposedException("Closed.", (Exception)null); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HidSharp/Device.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Diagnostics; 20 | using HidSharp.Utility; 21 | 22 | namespace HidSharp 23 | { 24 | public abstract class Device 25 | { 26 | /// 27 | /// Makes a connection to the device, or throws an exception if the connection cannot be made. 28 | /// 29 | /// The stream to use to communicate with the device. 30 | public DeviceStream Open() 31 | { 32 | return Open(null); 33 | } 34 | 35 | public DeviceStream Open(OpenConfiguration openConfig) 36 | { 37 | return OpenDeviceAndRestrictAccess(openConfig ?? new OpenConfiguration()); 38 | } 39 | 40 | protected virtual DeviceStream OpenDeviceAndRestrictAccess(OpenConfiguration openConfig) 41 | { 42 | bool exclusive = (bool)openConfig.GetOption(OpenOption.Exclusive); 43 | 44 | DeviceOpenUtility openUtility = null; 45 | if (exclusive) 46 | { 47 | string streamPath = GetStreamPath(openConfig); 48 | openUtility = new DeviceOpenUtility(this, streamPath, openConfig); 49 | openUtility.Open(); 50 | } 51 | 52 | DeviceStream stream; 53 | try 54 | { 55 | stream = OpenDeviceDirectly(openConfig); 56 | if (exclusive) 57 | { 58 | stream.Closed += (sender, e) => openUtility.Close(); 59 | openUtility.InterruptRequested += (sender, e) => 60 | { 61 | stream.OnInterruptRequested(); 62 | HidSharpDiagnostics.Trace("Delivered an interrupt request."); 63 | }; 64 | } 65 | } 66 | catch 67 | { 68 | if (exclusive) { openUtility.Close(); } 69 | throw; 70 | } 71 | 72 | return stream; 73 | } 74 | 75 | protected abstract DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig); 76 | 77 | // Used for exclusion... and also may be used inside OpenDeviceDirectly if desired. 78 | protected virtual string GetStreamPath(OpenConfiguration openConfig) 79 | { 80 | return DevicePath; 81 | } 82 | 83 | /// 84 | /// Tries to make a connection to the device. 85 | /// 86 | /// The stream to use to communicate with the device. 87 | /// true if the connection was successful. 88 | public bool TryOpen(out DeviceStream stream) 89 | { 90 | return TryOpen(null, out stream); 91 | } 92 | 93 | public bool TryOpen(OpenConfiguration openConfig, out DeviceStream stream) 94 | { 95 | Exception exception; 96 | return TryOpen(openConfig, out stream, out exception); 97 | } 98 | 99 | public bool TryOpen(OpenConfiguration openConfig, out DeviceStream stream, out Exception exception) 100 | { 101 | try 102 | { 103 | stream = Open(openConfig); exception = null; return true; 104 | } 105 | catch (Exception e) 106 | { 107 | Debug.WriteLine(e); 108 | stream = null; exception = e; return false; 109 | } 110 | } 111 | 112 | /// 113 | /// Returns the file system path of the device. 114 | /// This can be used to check permissions on Linux hidraw, for instance. 115 | /// 116 | /// The file system path. 117 | public abstract string GetFileSystemName(); 118 | 119 | /// 120 | /// Returns a name appropriate for display. 121 | /// 122 | /// The friendly name. 123 | public abstract string GetFriendlyName(); 124 | 125 | /// 126 | /// Checks if a particular implementation detail, such as the use of the Linux hidraw API, applies to this device. 127 | /// See for a list of possible details. 128 | /// 129 | /// The detail to check. 130 | /// true if the implementation detail applies. 131 | public virtual bool HasImplementationDetail(Guid detail) 132 | { 133 | return false; 134 | } 135 | 136 | /// 137 | /// The operating system's name for the device. 138 | /// 139 | /// If you have multiple devices with the same Vendor ID, Product ID, Serial Number, etc., 140 | /// this may be useful for differentiating them. 141 | /// 142 | public abstract string DevicePath 143 | { 144 | get; 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /HidSharp/DeviceException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.IO; 20 | 21 | namespace HidSharp 22 | { 23 | public static class DeviceException 24 | { 25 | /// 26 | /// Initializes a new instance of the class, and associates a with it. 27 | /// 28 | /// The device that caused the exception. 29 | /// A description of the error. 30 | /// The new . 31 | public static IOException CreateIOException(Device device, string message) 32 | { 33 | return new Exceptions.DeviceIOException(device, message); 34 | } 35 | 36 | /// 37 | /// Initializes a new instance of the class, and associates a with it. 38 | /// 39 | /// The device that caused the exception. 40 | /// A description of the error. 41 | /// An integer identifying the error that has occurred. 42 | /// The new . 43 | public static IOException CreateIOException(Device device, string message, int hresult) 44 | { 45 | return new Exceptions.DeviceIOException(device, message, hresult); 46 | } 47 | 48 | /// 49 | /// Initializes a new instance of the class, and associates a with it. 50 | /// 51 | /// The device that caused the exception. 52 | /// A description of the error. 53 | /// The new . 54 | public static UnauthorizedAccessException CreateUnauthorizedAccessException(Device device, string message) 55 | { 56 | return new Exceptions.DeviceUnauthorizedAccessException(device, message); 57 | } 58 | 59 | /// 60 | /// Gets the associated with the exception, if any. 61 | /// 62 | /// The exception to get the associated for. 63 | /// The associated , or null if none is associated with it. 64 | public static Device GetDevice(Exception exception) 65 | { 66 | var hidException = exception as Exceptions.IDeviceException; 67 | return hidException != null ? hidException.Device : null; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /HidSharp/DeviceFilter.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp 19 | { 20 | public delegate bool DeviceFilter(Device device); 21 | 22 | public static class DeviceFilterHelper 23 | { 24 | public static bool MatchHidDevices(Device device, int? vendorID = null, int? productID = null, int? releaseNumberBcd = null, string serialNumber = null) 25 | { 26 | var hidDevice = device as HidDevice; 27 | if (hidDevice != null) 28 | { 29 | int vid = vendorID ?? -1, pid = productID ?? -1, ver = releaseNumberBcd ?? -1; 30 | 31 | if ((vid < 0 || hidDevice.VendorID == vendorID) && 32 | (pid < 0 || hidDevice.ProductID == productID) && 33 | (ver < 0 || hidDevice.ReleaseNumberBcd == releaseNumberBcd)) 34 | { 35 | try 36 | { 37 | if (string.IsNullOrEmpty(serialNumber) || hidDevice.GetSerialNumber() == serialNumber) { return true; } 38 | } 39 | catch 40 | { 41 | 42 | } 43 | } 44 | } 45 | 46 | return false; 47 | } 48 | 49 | public static bool MatchSerialDevices(Device device, string portName = null) 50 | { 51 | var serialDevice = device as SerialDevice; 52 | if (serialDevice != null) 53 | { 54 | if (string.IsNullOrEmpty(portName) || serialDevice.DevicePath == portName) 55 | { 56 | return true; 57 | } 58 | } 59 | 60 | return false; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /HidSharp/DeviceListChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2016 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp 21 | { 22 | public class DeviceListChangedEventArgs : EventArgs 23 | { 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HidSharp/DeviceStream.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2016 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.IO; 20 | using HidSharp.Utility; 21 | 22 | namespace HidSharp 23 | { 24 | public abstract class DeviceStream : Stream 25 | { 26 | /// 27 | /// Occurs when the stream is closed. 28 | /// 29 | public event EventHandler Closed; 30 | 31 | /// 32 | /// Occurs when is true and another process or thread with higher priority 33 | /// would like to open the stream. 34 | /// 35 | public event EventHandler InterruptRequested; 36 | 37 | /// 38 | protected DeviceStream(Device device) 39 | { 40 | Throw.If.Null(device); 41 | Device = device; 42 | } 43 | 44 | /// 45 | protected override void Dispose(bool disposing) 46 | { 47 | try 48 | { 49 | OnClosed(); 50 | } 51 | catch (Exception e) 52 | { 53 | HidSharpDiagnostics.Trace("OnClosed threw an exception: {0}", e); 54 | } 55 | 56 | base.Dispose(disposing); 57 | } 58 | 59 | /// 60 | public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) 61 | { 62 | Throw.If.OutOfRange(buffer, offset, count); 63 | return AsyncResult.BeginOperation(delegate() 64 | { 65 | return Read(buffer, offset, count); 66 | }, callback, state); 67 | } 68 | 69 | /// 70 | public override int EndRead(IAsyncResult asyncResult) 71 | { 72 | return AsyncResult.EndOperation(asyncResult); 73 | } 74 | 75 | /// 76 | public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) 77 | { 78 | Throw.If.OutOfRange(buffer, offset, count); 79 | return AsyncResult.BeginOperation(delegate() 80 | { 81 | Write(buffer, offset, count); return 0; 82 | }, callback, state); 83 | } 84 | 85 | /// 86 | public override void EndWrite(IAsyncResult asyncResult) 87 | { 88 | AsyncResult.EndOperation(asyncResult); 89 | } 90 | 91 | /// 92 | public override long Seek(long offset, SeekOrigin origin) 93 | { 94 | throw new NotSupportedException(); 95 | } 96 | 97 | /// 98 | public override void SetLength(long value) 99 | { 100 | throw new NotSupportedException(); 101 | } 102 | 103 | protected virtual void OnClosed() 104 | { 105 | RaiseClosed(); 106 | } 107 | 108 | protected void RaiseClosed() 109 | { 110 | var ev = Closed; 111 | if (ev != null) { ev(this, EventArgs.Empty); } 112 | } 113 | 114 | protected internal virtual void OnInterruptRequested() 115 | { 116 | RaiseInterruptRequested(); 117 | } 118 | 119 | protected void RaiseInterruptRequested() 120 | { 121 | var ev = InterruptRequested; 122 | if (ev != null) { ev(this, EventArgs.Empty); } 123 | } 124 | 125 | /// 126 | public override bool CanRead 127 | { 128 | get { return true; } 129 | } 130 | 131 | /// 132 | public override bool CanSeek 133 | { 134 | get { return false; } 135 | } 136 | 137 | /// 138 | public override bool CanWrite 139 | { 140 | get { return true; } 141 | } 142 | 143 | /// 144 | public override bool CanTimeout 145 | { 146 | get { return true; } 147 | } 148 | 149 | /// 150 | /// Gets the associated with this stream. 151 | /// 152 | public Device Device 153 | { 154 | get; 155 | private set; 156 | } 157 | 158 | /// 159 | public override long Length 160 | { 161 | get { throw new NotSupportedException(); } 162 | } 163 | 164 | /// 165 | public override long Position 166 | { 167 | get { throw new NotSupportedException(); } 168 | set { throw new NotSupportedException(); } 169 | } 170 | 171 | /// 172 | /// The maximum amount of time, in milliseconds, to wait for the device to send some data. 173 | /// 174 | /// The default is 3000 milliseconds. 175 | /// To disable the timeout, set this to . 176 | /// 177 | public abstract override int ReadTimeout 178 | { 179 | get; 180 | set; 181 | } 182 | 183 | /// 184 | /// The maximum amount of time, in milliseconds, to wait for the device to receive the data. 185 | /// 186 | /// The default is 3000 milliseconds. 187 | /// To disable the timeout, set this to . 188 | /// 189 | public abstract override int WriteTimeout 190 | { 191 | get; 192 | set; 193 | } 194 | 195 | /// 196 | /// An object storing user-defined data about the stream. 197 | /// 198 | public object Tag 199 | { 200 | get; 201 | set; 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /HidSharp/DeviceTypes.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp 21 | { 22 | [Flags] 23 | public enum DeviceTypes 24 | { 25 | Hid = 1, 26 | Serial = 2, 27 | Ble = 4 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HidSharp/Exceptions/DeviceIOException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.IO; 19 | 20 | namespace HidSharp.Exceptions 21 | { 22 | sealed class DeviceIOException : IOException, IDeviceException 23 | { 24 | public DeviceIOException(Device device, string message) 25 | : base(message) 26 | { 27 | Device = device; 28 | } 29 | 30 | public DeviceIOException(Device device, string message, int hresult) 31 | : base(message, hresult) 32 | { 33 | Device = device; 34 | } 35 | 36 | public Device Device 37 | { 38 | get; 39 | private set; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /HidSharp/Exceptions/DeviceUnauthorizedAccessException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Exceptions 21 | { 22 | sealed class DeviceUnauthorizedAccessException : UnauthorizedAccessException, IDeviceException 23 | { 24 | public DeviceUnauthorizedAccessException(Device device, string message) 25 | : base(message) 26 | { 27 | Device = device; 28 | } 29 | 30 | public Device Device 31 | { 32 | get; 33 | private set; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /HidSharp/Exceptions/IDeviceException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Exceptions 19 | { 20 | interface IDeviceException 21 | { 22 | Device Device { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleCccd.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | [Flags] 23 | public enum BleCccd : ushort 24 | { 25 | None = 0, 26 | Notification = 1, 27 | Indication = 2 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleCharacteristic.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | public abstract class BleCharacteristic 23 | { 24 | public override string ToString() 25 | { 26 | return string.Format("{0} (properties: {1})", Uuid, Properties); 27 | } 28 | 29 | public abstract BleDescriptor[] GetDescriptors(); 30 | 31 | public bool HasDescriptor(BleUuid uuid) 32 | { 33 | BleDescriptor descriptor; 34 | return TryGetDescriptor(uuid, out descriptor); 35 | } 36 | 37 | public BleDescriptor GetDescriptorOrNull(BleUuid uuid) 38 | { 39 | BleDescriptor descriptor; 40 | return TryGetDescriptor(uuid, out descriptor) ? descriptor : null; 41 | } 42 | 43 | public virtual bool TryGetDescriptor(BleUuid uuid, out BleDescriptor descriptor) 44 | { 45 | foreach (var d in GetDescriptors()) 46 | { 47 | if (d.Uuid == uuid) { descriptor = d; return true; } 48 | } 49 | 50 | descriptor = null; return false; 51 | } 52 | 53 | public abstract BleUuid Uuid 54 | { 55 | get; 56 | } 57 | 58 | public abstract BleCharacteristicProperties Properties 59 | { 60 | get; 61 | } 62 | 63 | public bool IsReadable 64 | { 65 | get { return (Properties & BleCharacteristicProperties.Read) != 0; } 66 | } 67 | 68 | public bool IsWritable 69 | { 70 | get { return (Properties & BleCharacteristicProperties.Write) != 0; } 71 | } 72 | 73 | public bool IsWritableWithoutResponse 74 | { 75 | get { return (Properties & BleCharacteristicProperties.WriteWithoutResponse) != 0; } 76 | } 77 | 78 | public bool IsNotifiable 79 | { 80 | get { return (Properties & BleCharacteristicProperties.Notify) != 0; } 81 | } 82 | 83 | public bool IsIndicatable 84 | { 85 | get { return (Properties & BleCharacteristicProperties.Indicate) != 0; } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleCharacteristicProperties.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | [Flags] 23 | public enum BleCharacteristicProperties : byte 24 | { 25 | None = 0x00, 26 | Broadcast = 0x01, 27 | Read = 0x02, 28 | WriteWithoutResponse = 0x04, 29 | Write = 0x08, 30 | Notify = 0x10, 31 | Indicate = 0x20, 32 | SignedWrite = 0x40, 33 | ExtendedProperties = 0x80 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleDescriptor.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | public abstract class BleDescriptor 23 | { 24 | public override string ToString() 25 | { 26 | return Uuid.ToString(); 27 | } 28 | 29 | public abstract BleUuid Uuid 30 | { 31 | get; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleDevice.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.ComponentModel; 20 | using System.Runtime.CompilerServices; 21 | using System.Runtime.InteropServices; 22 | 23 | namespace HidSharp.Experimental 24 | { 25 | /// 26 | /// Represents a Bluetooth Low Energy device. 27 | /// 28 | [ComVisible(true), Guid("A7AEE7B8-893D-41B6-84F7-6BDA4EE3AA3F")] 29 | public abstract class BleDevice : Device 30 | { 31 | /// 32 | [EditorBrowsable(EditorBrowsableState.Never)] 33 | public new BleStream Open() 34 | { 35 | return (BleStream)base.Open(); 36 | } 37 | 38 | /// 39 | [EditorBrowsable(EditorBrowsableState.Never)] 40 | public new BleStream Open(OpenConfiguration openConfig) 41 | { 42 | return (BleStream)base.Open(openConfig); 43 | } 44 | 45 | public BleStream Open(BleService service) 46 | { 47 | return Open(service, new OpenConfiguration()); 48 | } 49 | 50 | public BleStream Open(BleService service, OpenConfiguration openConfig) 51 | { 52 | Throw.If.Null(service).Null(openConfig); 53 | 54 | openConfig = openConfig.Clone(); 55 | openConfig.SetOption(OpenOption.BleService, service); 56 | return Open(openConfig); 57 | } 58 | 59 | /* 60 | public abstract bool GetConnectionState(); 61 | */ 62 | 63 | public abstract BleService[] GetServices(); 64 | 65 | public BleService GetServiceOrNull(BleUuid uuid) 66 | { 67 | BleService service; 68 | return TryGetService(uuid, out service) ? service : null; 69 | } 70 | 71 | public virtual bool HasService(BleUuid uuid) 72 | { 73 | BleService service; 74 | return TryGetService(uuid, out service); 75 | } 76 | 77 | public virtual bool TryGetService(BleUuid uuid, out BleService service) 78 | { 79 | foreach (var s in GetServices()) 80 | { 81 | if (s.Uuid == uuid) { service = s; return true; } 82 | } 83 | 84 | service = null; return false; 85 | } 86 | 87 | public override bool HasImplementationDetail(Guid detail) 88 | { 89 | return base.HasImplementationDetail(detail) || detail == ImplementationDetail.BleDevice; 90 | } 91 | 92 | public override string ToString() 93 | { 94 | string friendlyName = "(unknown friendly name)"; 95 | try { friendlyName = GetFriendlyName(); } 96 | catch { } 97 | 98 | return friendlyName; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleDiscovery.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | abstract class BleDiscovery : IDisposable 23 | { 24 | public abstract void StopDiscovery(); 25 | 26 | void IDisposable.Dispose() 27 | { 28 | StopDiscovery(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace HidSharp.Experimental 7 | { 8 | public struct BleEvent 9 | { 10 | BleCharacteristic _characteristic; 11 | byte[] _value; 12 | 13 | public BleEvent(BleCharacteristic characteristic, byte[] value) 14 | { 15 | _characteristic = characteristic; _value = value; 16 | } 17 | 18 | public BleCharacteristic Characteristic 19 | { 20 | get { return _characteristic; } 21 | } 22 | 23 | public byte[] Value 24 | { 25 | get { return _value; } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleRequestFlags.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | [Flags] 23 | public enum BleRequestFlags 24 | { 25 | None = 0, 26 | Authenticated = 1, 27 | Encrypted = 2, 28 | Cacheable = 4 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleService.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Experimental 21 | { 22 | public abstract class BleService 23 | { 24 | public override string ToString() 25 | { 26 | return Uuid.ToString(); 27 | } 28 | 29 | public abstract BleCharacteristic[] GetCharacteristics(); 30 | 31 | public BleCharacteristic GetCharacteristicOrNull(BleUuid uuid) 32 | { 33 | BleCharacteristic characteristic; 34 | return TryGetCharacteristic(uuid, out characteristic) ? characteristic : null; 35 | } 36 | 37 | public virtual bool HasCharacteristic(BleUuid uuid) 38 | { 39 | BleCharacteristic characteristic; 40 | return TryGetCharacteristic(uuid, out characteristic); 41 | } 42 | 43 | public virtual bool TryGetCharacteristic(BleUuid uuid, out BleCharacteristic characteristic) 44 | { 45 | foreach (var c in GetCharacteristics()) 46 | { 47 | if (c.Uuid == uuid) { characteristic = c; return true; } 48 | } 49 | 50 | characteristic = null; return false; 51 | } 52 | 53 | public abstract BleDevice Device 54 | { 55 | get; 56 | } 57 | 58 | public abstract BleUuid Uuid 59 | { 60 | get; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleUuid.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Globalization; 20 | 21 | namespace HidSharp.Experimental 22 | { 23 | public struct BleUuid : IEquatable 24 | { 25 | Guid _guid; 26 | 27 | public BleUuid(int uuid) : this() 28 | { 29 | Initialize(uuid); 30 | } 31 | 32 | public BleUuid(Guid guid) : this() 33 | { 34 | Initialize(guid); 35 | } 36 | 37 | public BleUuid(string uuid) : this() 38 | { 39 | Initialize(uuid); 40 | } 41 | 42 | void Initialize(int uuid) 43 | { 44 | _guid = new Guid(uuid, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB); 45 | } 46 | 47 | void Initialize(Guid guid) 48 | { 49 | _guid = guid; 50 | } 51 | 52 | void Initialize(string guid) 53 | { 54 | uint shortUuid; 55 | if (uint.TryParse(guid, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out shortUuid)) 56 | { 57 | Initialize((int)shortUuid); 58 | } 59 | else 60 | { 61 | Initialize(new Guid(guid)); 62 | } 63 | } 64 | 65 | public override bool Equals(object other) 66 | { 67 | return other is BleUuid && Equals((BleUuid)other); 68 | } 69 | 70 | public bool Equals(BleUuid other) 71 | { 72 | return _guid.Equals(other._guid); 73 | } 74 | 75 | public override int GetHashCode() 76 | { 77 | return _guid.GetHashCode(); 78 | } 79 | 80 | public static implicit operator BleUuid(Guid guid) 81 | { 82 | return new BleUuid(guid); 83 | } 84 | 85 | public static implicit operator Guid(BleUuid uuid) 86 | { 87 | return uuid.ToGuid(); 88 | } 89 | 90 | public int ToShortUuid() 91 | { 92 | if (!IsShortUuid) { throw new InvalidOperationException(); } 93 | 94 | byte[] bytes = _guid.ToByteArray(); 95 | return (ushort)(bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24); 96 | } 97 | 98 | static void SwapNetworkOrder(byte[] guid) 99 | { 100 | byte temp; 101 | temp = guid[0]; guid[0] = guid[3]; guid[3] = temp; 102 | temp = guid[1]; guid[1] = guid[2]; guid[2] = temp; 103 | temp = guid[4]; guid[4] = guid[5]; guid[5] = temp; 104 | temp = guid[6]; guid[6] = guid[7]; guid[7] = temp; 105 | } 106 | 107 | public byte[] ToByteArray() 108 | { 109 | var guid = _guid.ToByteArray(); 110 | SwapNetworkOrder(guid); 111 | return guid; 112 | } 113 | 114 | public Guid ToGuid() 115 | { 116 | return _guid; 117 | } 118 | 119 | public override string ToString() 120 | { 121 | return IsShortUuid ? ToShortUuid().ToString("X", CultureInfo.InvariantCulture) : ToGuid().ToString("D", CultureInfo.InvariantCulture); 122 | } 123 | 124 | public bool IsShortUuid 125 | { 126 | get 127 | { 128 | byte[] bytes = _guid.ToByteArray(); 129 | return bytes[4] == 0x00 && bytes[5] == 0x00 130 | && bytes[6] == 0x00 && bytes[7] == 0x10 131 | && bytes[8] == 0x80 && bytes[9] == 0x00 && bytes[10] == 0x00 && bytes[11] == 0x80 && bytes[12] == 0x5F && bytes[13] == 0x9B && bytes[14] == 0x34 && bytes[15] == 0xFB; 132 | } 133 | } 134 | 135 | public static bool operator ==(BleUuid lhs, BleUuid rhs) 136 | { 137 | return lhs.Equals(rhs); 138 | } 139 | 140 | public static bool operator !=(BleUuid lhs, BleUuid rhs) 141 | { 142 | return !lhs.Equals(rhs); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /HidSharp/Experimental/BleUuids.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Experimental 19 | { 20 | static class BleUuids 21 | { 22 | public static readonly BleUuid Cccd = new BleUuid(0x2902); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /HidSharp/FilteredDeviceList.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2016-2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | using System.Threading; 22 | 23 | namespace HidSharp 24 | { 25 | public class FilteredDeviceList : DeviceList 26 | { 27 | int _dirty; 28 | List> _areDriversBeingInstalled; 29 | Dictionary _refCounts; 30 | 31 | public FilteredDeviceList() 32 | { 33 | _areDriversBeingInstalled = new List>(); 34 | _refCounts = new Dictionary(); 35 | } 36 | 37 | /* 38 | public override BleDiscovery BeginBleDiscovery() 39 | { 40 | throw new NotImplementedException(); 41 | } 42 | */ 43 | 44 | public void Add(Device device) 45 | { 46 | Throw.If.Null(device, "device"); 47 | 48 | lock (_refCounts) 49 | { 50 | IncrementRefCount(device); 51 | } 52 | 53 | RaiseChangedIfDirty(); 54 | } 55 | 56 | public void Add(DeviceList deviceList) 57 | { 58 | Add(deviceList, device => true); 59 | } 60 | 61 | public void Add(DeviceList deviceList, DeviceFilter filter) 62 | { 63 | Throw.If.Null(deviceList, "deviceList").Null(filter, "filter"); 64 | 65 | var oldDevices = new Device[0]; 66 | Action updateDeviceList = () => 67 | { 68 | var newDevices = deviceList.GetAllDevices(filter).ToArray(); 69 | 70 | lock (_refCounts) 71 | { 72 | foreach (var newDevice in newDevices) 73 | { 74 | IncrementRefCount(newDevice); 75 | } 76 | 77 | foreach (var oldDevice in oldDevices) 78 | { 79 | DecrementRefCount(oldDevice); 80 | } 81 | } 82 | 83 | oldDevices = newDevices; 84 | RaiseChangedIfDirty(); 85 | }; 86 | 87 | _areDriversBeingInstalled.Add(() => deviceList.AreDriversBeingInstalled); 88 | deviceList.Changed += (sender, e) => updateDeviceList(); 89 | updateDeviceList(); 90 | } 91 | 92 | /// 93 | public override IEnumerable GetAllDevices() 94 | { 95 | lock (_refCounts) 96 | { 97 | return _refCounts.Keys.ToList(); 98 | } 99 | } 100 | 101 | void IncrementRefCount(Device device) 102 | { 103 | if (_refCounts.ContainsKey(device)) 104 | { 105 | _refCounts[device]++; 106 | } 107 | else 108 | { 109 | _refCounts[device] = 1; _dirty = 1; 110 | } 111 | } 112 | 113 | void DecrementRefCount(Device device) 114 | { 115 | if (--_refCounts[device] == 0) 116 | { 117 | _refCounts.Remove(device); _dirty = 1; 118 | } 119 | } 120 | 121 | void RaiseChangedIfDirty() 122 | { 123 | if (1 == Interlocked.CompareExchange(ref _dirty, 0, 1)) 124 | { 125 | RaiseChanged(); 126 | } 127 | } 128 | 129 | /// 130 | public override bool AreDriversBeingInstalled 131 | { 132 | get { return _areDriversBeingInstalled.Any(callback => callback()); } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /HidSharp/HidDeviceLoader.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2010, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections; 20 | using System.Collections.Generic; 21 | using System.ComponentModel; 22 | using System.Runtime.InteropServices; 23 | 24 | namespace HidSharp 25 | { 26 | /// 27 | [ComVisible(true), Guid("CD7CBD7D-7204-473c-AA2A-2B9622CFC6CC")] 28 | [Obsolete, EditorBrowsable(EditorBrowsableState.Never)] 29 | public class HidDeviceLoader 30 | { 31 | /// 32 | [Obsolete, EditorBrowsable(EditorBrowsableState.Never)] 33 | public HidDeviceLoader() 34 | { 35 | 36 | } 37 | 38 | /// 39 | [Obsolete, EditorBrowsable(EditorBrowsableState.Never)] 40 | public IEnumerable GetDevicesVB() 41 | { 42 | return DeviceList.Local.GetHidDevices(); 43 | } 44 | 45 | /// 46 | [Obsolete, EditorBrowsable(EditorBrowsableState.Never)] 47 | public IEnumerable GetDevices() 48 | { 49 | return DeviceList.Local.GetHidDevices(); 50 | } 51 | 52 | /// 53 | [Obsolete, EditorBrowsable(EditorBrowsableState.Never)] 54 | public IEnumerable GetDevices(int? vendorID = null, int? productID = null, int? productVersion = null, string serialNumber = null) 55 | { 56 | return DeviceList.Local.GetHidDevices(vendorID, productID, productVersion, serialNumber); 57 | } 58 | 59 | /// 60 | [Obsolete, EditorBrowsable(EditorBrowsableState.Never)] 61 | public HidDevice GetDeviceOrDefault(int? vendorID = null, int? productID = null, int? productVersion = null, string serialNumber = null) 62 | { 63 | return DeviceList.Local.GetHidDeviceOrNull(vendorID, productID, productVersion, serialNumber); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /HidSharp/HidSharp.NETStandard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | false 7 | HidSharp 8 | HidSharp 9 | ..\bin 10 | ..\bin\netstandard2.0\HidSharp.XML 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /HidSharp/HidSharp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | Library 5 | false 6 | ..\bin\ 7 | Illusory Studios LLC 8 | Copyright © 2010-2019 James F. Bellinger <http://www.zer7.com/software/hidsharp> 9 | C# HID wrappers 10 | HidSharp 11 | HidSharp 12 | 2.1.0.0 13 | 2.1.0.0 14 | 2.1.0 15 | True 16 | 17 | -------------------------------------------------------------------------------- /HidSharp/HidStream.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012-2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Runtime.InteropServices; 20 | 21 | #pragma warning disable 420 22 | 23 | namespace HidSharp 24 | { 25 | /// 26 | /// Communicates with a USB HID class device. 27 | /// 28 | [ComVisible(true), Guid("0C263D05-0D58-4c6c-AEA7-EB9E0C5338A2")] 29 | public abstract class HidStream : DeviceStream 30 | { 31 | /// 32 | protected HidStream(HidDevice device) 33 | : base(device) 34 | { 35 | ReadTimeout = 3000; 36 | WriteTimeout = 3000; 37 | } 38 | 39 | /// 40 | public override void Flush() 41 | { 42 | 43 | } 44 | 45 | /// 46 | /// Sends a Get Feature setup request. 47 | /// 48 | /// The buffer to fill. Place the Report ID in the first byte. 49 | public void GetFeature(byte[] buffer) 50 | { 51 | Throw.If.Null(buffer, "buffer"); 52 | GetFeature(buffer, 0, buffer.Length); 53 | } 54 | 55 | /// 56 | /// Sends a Get Feature setup request. 57 | /// 58 | /// The buffer to fill. Place the Report ID in the byte at index . 59 | /// The index in the buffer to begin filling with data. 60 | /// The number of bytes in the feature request. 61 | public abstract void GetFeature(byte[] buffer, int offset, int count); 62 | 63 | /// 64 | /// Reads HID Input Reports. 65 | /// 66 | /// The data read. 67 | public byte[] Read() 68 | { 69 | byte[] buffer = new byte[Device.GetMaxInputReportLength()]; 70 | int bytes = Read(buffer); Array.Resize(ref buffer, bytes); 71 | return buffer; 72 | } 73 | 74 | /// 75 | /// Reads HID Input Reports. 76 | /// 77 | /// The buffer to place the reports into. 78 | /// The number of bytes read. 79 | public int Read(byte[] buffer) 80 | { 81 | Throw.If.Null(buffer, "buffer"); 82 | return Read(buffer, 0, buffer.Length); 83 | } 84 | 85 | /// 86 | /// Sends a Set Feature setup request. 87 | /// 88 | /// The buffer of data to send. Place the Report ID in the first byte. 89 | public void SetFeature(byte[] buffer) 90 | { 91 | Throw.If.Null(buffer, "buffer"); 92 | SetFeature(buffer, 0, buffer.Length); 93 | } 94 | 95 | /// 96 | /// Sends a Set Feature setup request. 97 | /// 98 | /// The buffer of data to send. Place the Report ID in the byte at index . 99 | /// The index in the buffer to start the write from. 100 | /// The number of bytes in the feature request. 101 | public abstract void SetFeature(byte[] buffer, int offset, int count); 102 | 103 | /// 104 | /// Writes an HID Output Report to the device. 105 | /// 106 | /// The buffer containing the report. Place the Report ID in the first byte. 107 | public void Write(byte[] buffer) 108 | { 109 | Throw.If.Null(buffer, "buffer"); 110 | Write(buffer, 0, buffer.Length); 111 | } 112 | 113 | /// 114 | /// Gets the associated with this stream. 115 | /// 116 | public new HidDevice Device 117 | { 118 | get { return (HidDevice)base.Device; } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /HidSharp/ImplementationDetail.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp 21 | { 22 | /// 23 | /// Specifies the 's low-level implementation. 24 | /// 25 | public static class ImplementationDetail 26 | { 27 | /// 28 | /// The device is running on Windows. 29 | /// 30 | public static Guid Windows { get; private set; } 31 | 32 | /// 33 | /// The device is running on a Mac. 34 | /// 35 | public static Guid MacOS { get; private set; } 36 | 37 | /// 38 | /// The device is running on Linux. 39 | /// 40 | public static Guid Linux { get; private set; } 41 | 42 | /// 43 | /// The device is a Bluetooth Low Energy device. 44 | /// 45 | public static Guid BleDevice { get; private set; } 46 | 47 | /// 48 | /// The device is a HID device. 49 | /// 50 | public static Guid HidDevice { get; private set; } 51 | 52 | /// 53 | /// The device is a serial device. 54 | /// 55 | public static Guid SerialDevice { get; private set; } 56 | 57 | /// 58 | /// The device is implemented using the Linux hidraw API. 59 | /// 60 | public static Guid HidrawApi { get; private set; } 61 | 62 | static ImplementationDetail() 63 | { 64 | Windows = new Guid("{3540D886-E329-419F-8033-1D7355D53A7E}"); 65 | MacOS = new Guid("{9FE992E5-F804-41B6-A35F-3B60F7CAC9E2}"); 66 | Linux = new Guid("{A4123219-6BC8-49B7-84D3-699A66373109}"); 67 | 68 | BleDevice = new Guid("{AAFD1479-29A0-42B8-A0A9-5C88A18B5504}"); 69 | HidDevice = new Guid("{DFF209D7-131E-4958-8F47-C23DAC7B62DA}"); 70 | SerialDevice = new Guid("{45A96DA9-AA48-4BF7-978D-A845F185F38C}"); 71 | 72 | HidrawApi = new Guid("{1199D7C6-F99F-471F-9730-B16BA615938F}"); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /HidSharp/LocalDeviceList.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace HidSharp 21 | { 22 | sealed class LocalDeviceList : DeviceList 23 | { 24 | /* 25 | public override BleDiscovery BeginBleDiscovery() 26 | { 27 | return Platform.HidSelector.Instance.BeginBleDiscovery(); 28 | } 29 | */ 30 | 31 | public override IEnumerable GetDevices(DeviceTypes types) 32 | { 33 | return Platform.HidSelector.Instance.GetDevices(types); 34 | } 35 | 36 | public override IEnumerable GetAllDevices() 37 | { 38 | return GetDevices(DeviceTypes.Hid | DeviceTypes.Serial | DeviceTypes.Ble); 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return Platform.HidSelector.Instance.FriendlyName; // This value is useful for debugging. 44 | } 45 | 46 | public override bool AreDriversBeingInstalled 47 | { 48 | get { return Platform.HidSelector.Instance.AreDriversBeingInstalled; } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /HidSharp/OpenConfiguration.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2016, 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | 21 | namespace HidSharp 22 | { 23 | /// 24 | /// Describes all options for opening a device stream. 25 | /// 26 | public class OpenConfiguration : ICloneable 27 | { 28 | Dictionary _options; 29 | 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | public OpenConfiguration() 34 | { 35 | _options = new Dictionary(); 36 | } 37 | 38 | OpenConfiguration(Dictionary options) 39 | { 40 | _options = new Dictionary(options); 41 | } 42 | 43 | public OpenConfiguration Clone() 44 | { 45 | return new OpenConfiguration(_options); 46 | } 47 | 48 | object ICloneable.Clone() 49 | { 50 | return Clone(); 51 | } 52 | 53 | /// 54 | /// Gets the current value of an option. 55 | /// 56 | /// The option. 57 | /// The option's value. 58 | public object GetOption(OpenOption option) 59 | { 60 | Throw.If.Null(option, "option"); 61 | 62 | object value; 63 | return _options.TryGetValue(option, out value) ? value : option.DefaultValue; 64 | } 65 | 66 | /// 67 | /// Gets a list of all currently set options. 68 | /// 69 | /// The options list. 70 | public IEnumerable GetOptionsList() 71 | { 72 | return _options.Keys; 73 | } 74 | 75 | /// 76 | /// Checks if an option has been set. 77 | /// 78 | /// The option. 79 | /// true if the option has been set. 80 | public bool IsOptionSet(OpenOption option) 81 | { 82 | Throw.If.Null(option, "option"); 83 | 84 | return _options.ContainsKey(option); 85 | } 86 | 87 | /// 88 | /// Sets the current value of an option. 89 | /// 90 | /// The option. 91 | /// The value to set it to. 92 | public void SetOption(OpenOption option, object value) 93 | { 94 | Throw.If.Null(option, "option"); 95 | 96 | if (value != null) 97 | { 98 | _options[option] = value; 99 | } 100 | else 101 | { 102 | _options.Remove(option); 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /HidSharp/OpenPriority.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2016 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp 19 | { 20 | /// 21 | /// The priority at which to open a device stream. 22 | /// 23 | public enum OpenPriority 24 | { 25 | /// 26 | /// The lowest priority. 27 | /// 28 | Idle = -2, 29 | 30 | /// 31 | /// Very low priority. 32 | /// 33 | VeryLow = -1, 34 | 35 | /// 36 | /// Low priority. 37 | /// 38 | Low = 0, 39 | 40 | /// 41 | /// The default priority. 42 | /// 43 | Normal = 1, 44 | 45 | /// 46 | /// High priority. 47 | /// 48 | High = 2, 49 | 50 | /// 51 | /// The highest priority. 52 | /// 53 | VeryHigh = 3 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /HidSharp/Platform/HidManager.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012-2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | using System.Threading; 22 | using HidSharp.Experimental; 23 | using HidSharp.Utility; 24 | 25 | namespace HidSharp.Platform 26 | { 27 | abstract class HidManager 28 | { 29 | sealed class DeviceTypeInfo 30 | { 31 | public delegate object[] GetDeviceKeysCallbackType(); 32 | public delegate bool TryCreateDeviceCallbackType(object key, out Device device); 33 | 34 | public object DevicesLock = new object(); 35 | public Dictionary DeviceList = new Dictionary(); 36 | public GetDeviceKeysCallbackType GetDeviceKeysCallback; 37 | public TryCreateDeviceCallbackType TryCreateDeviceCallback; 38 | } 39 | DeviceTypeInfo _ble, _hid, _serial; 40 | 41 | protected HidManager() 42 | { 43 | _ble = new DeviceTypeInfo() 44 | { 45 | GetDeviceKeysCallback = GetBleDeviceKeys, 46 | TryCreateDeviceCallback = TryCreateBleDevice 47 | }; 48 | 49 | _hid = new DeviceTypeInfo() 50 | { 51 | GetDeviceKeysCallback = GetHidDeviceKeys, 52 | TryCreateDeviceCallback = TryCreateHidDevice 53 | }; 54 | 55 | _serial = new DeviceTypeInfo() 56 | { 57 | GetDeviceKeysCallback = GetSerialDeviceKeys, 58 | TryCreateDeviceCallback = TryCreateSerialDevice 59 | }; 60 | } 61 | 62 | internal void InitializeEventManager() 63 | { 64 | EventManager = CreateEventManager(); 65 | EventManager.Start(); 66 | } 67 | 68 | protected virtual SystemEvents.EventManager CreateEventManager() 69 | { 70 | return new SystemEvents.DefaultEventManager(); 71 | } 72 | 73 | protected virtual void Run(Action readyCallback) 74 | { 75 | readyCallback(); 76 | } 77 | 78 | internal void RunImpl(object readyEvent) 79 | { 80 | Run(() => ((ManualResetEvent)readyEvent).Set()); 81 | } 82 | 83 | protected static void RunAssert(bool condition, string error) 84 | { 85 | if (!condition) { throw new InvalidOperationException(error); } 86 | } 87 | 88 | public virtual BleDiscovery BeginBleDiscovery() 89 | { 90 | throw new NotSupportedException(); 91 | } 92 | 93 | IEnumerable GetDevices(DeviceTypeInfo type) 94 | { 95 | var _deviceList = type.DeviceList; 96 | var devicesLock = type.DevicesLock; 97 | var getDeviceKeysCallback = type.GetDeviceKeysCallback; 98 | var tryCreateDeviceCallback = type.TryCreateDeviceCallback; 99 | 100 | Device[] deviceListArray; 101 | 102 | lock (devicesLock) 103 | { 104 | object[] devices = getDeviceKeysCallback(); 105 | object[] additions = devices.Except(_deviceList.Keys).ToArray(); 106 | object[] removals = _deviceList.Keys.Except(devices).ToArray(); 107 | 108 | if (additions.Length > 0) 109 | { 110 | int completedAdditions = 0; 111 | 112 | foreach (object addition in additions) 113 | { 114 | ThreadPool.QueueUserWorkItem(new WaitCallback(key => 115 | { 116 | Device device; 117 | bool created = tryCreateDeviceCallback(key, out device); 118 | 119 | if (created) 120 | { 121 | // By not adding on failure, we'll end up retrying every time. 122 | lock (_deviceList) 123 | { 124 | _deviceList.Add(key, device); 125 | HidSharpDiagnostics.Trace("Detected a new device: {0}", key); 126 | } 127 | } 128 | 129 | lock (_deviceList) 130 | { 131 | completedAdditions++; Monitor.Pulse(_deviceList); 132 | } 133 | }), addition); 134 | } 135 | 136 | lock (_deviceList) 137 | { 138 | while (completedAdditions != additions.Length) { Monitor.Wait(_deviceList); } 139 | } 140 | } 141 | 142 | foreach (object key in removals) 143 | { 144 | _deviceList.Remove(key); 145 | HidSharpDiagnostics.Trace("Detected a device removal: {0}", key); 146 | } 147 | deviceListArray = _deviceList.Values.ToArray(); 148 | } 149 | 150 | return deviceListArray; 151 | } 152 | 153 | public IEnumerable GetDevices(DeviceTypes types) 154 | { 155 | var devices = Enumerable.Empty(); 156 | if (0 != (types & DeviceTypes.Hid)) { devices = devices.Concat(GetDevices(_hid)); } 157 | if (0 != (types & DeviceTypes.Serial)) { devices = devices.Concat(GetDevices(_serial)); } 158 | if (0 != (types & DeviceTypes.Ble)) { devices = devices.Concat(GetDevices(_ble)); } 159 | return devices; 160 | } 161 | 162 | protected abstract object[] GetBleDeviceKeys(); 163 | 164 | protected abstract object[] GetHidDeviceKeys(); 165 | 166 | protected abstract object[] GetSerialDeviceKeys(); 167 | 168 | protected abstract bool TryCreateBleDevice(object key, out Device device); 169 | 170 | protected abstract bool TryCreateHidDevice(object key, out Device device); 171 | 172 | protected abstract bool TryCreateSerialDevice(object key, out Device device); 173 | 174 | public virtual bool AreDriversBeingInstalled 175 | { 176 | get { return false; } 177 | } 178 | 179 | public SystemEvents.EventManager EventManager 180 | { 181 | get; 182 | private set; 183 | } 184 | 185 | public abstract string FriendlyName 186 | { 187 | get; 188 | } 189 | 190 | public abstract bool IsSupported 191 | { 192 | get; 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /HidSharp/Platform/HidSelector.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012-2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Threading; 19 | 20 | namespace HidSharp.Platform 21 | { 22 | sealed class HidSelector 23 | { 24 | public static readonly HidManager Instance; 25 | static readonly Thread ManagerThread; 26 | 27 | static HidSelector() 28 | { 29 | foreach (var hidManager in new HidManager[] 30 | { 31 | new Windows.WinHidManager(), 32 | new Linux.LinuxHidManager(), 33 | new MacOS.MacHidManager(), 34 | new Unsupported.UnsupportedHidManager() 35 | }) 36 | { 37 | if (hidManager.IsSupported) 38 | { 39 | var readyEvent = new ManualResetEvent(false); 40 | 41 | Instance = hidManager; 42 | Instance.InitializeEventManager(); 43 | ManagerThread = new Thread(Instance.RunImpl) { IsBackground = true, Name = "HID Manager" }; 44 | ManagerThread.Start(readyEvent); 45 | readyEvent.WaitOne(); 46 | break; 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /HidSharp/Platform/Libusb/LibusbHidManager.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Platform.Libusb 21 | { 22 | sealed class LibusbHidManager 23 | { 24 | // TODO 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /HidSharp/Platform/Linux/LinuxSerialDevice.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017-2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Platform.Linux 21 | { 22 | sealed class LinuxSerialDevice : SerialDevice 23 | { 24 | string _portName; 25 | 26 | protected override DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig) 27 | { 28 | return new LinuxSerialStream(this); 29 | } 30 | 31 | internal static LinuxSerialDevice TryCreate(string portName) 32 | { 33 | return new LinuxSerialDevice() { _portName = portName }; 34 | } 35 | 36 | public override string GetFileSystemName() 37 | { 38 | return _portName; 39 | } 40 | 41 | public override bool HasImplementationDetail(Guid detail) 42 | { 43 | return base.HasImplementationDetail(detail) || detail == ImplementationDetail.Linux; 44 | } 45 | 46 | public override string DevicePath 47 | { 48 | get { return _portName; } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /HidSharp/Platform/Linux/NativeMethodsLibudev.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2016 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Platform.Linux 21 | { 22 | abstract class NativeMethodsLibudev 23 | { 24 | static NativeMethodsLibudev() 25 | { 26 | foreach (var instance in new NativeMethodsLibudev[] { new NativeMethodsLibudev1(), new NativeMethodsLibudev0() }) 27 | { 28 | try 29 | { 30 | IntPtr udev = instance.udev_new(); 31 | if (IntPtr.Zero != udev) 32 | { 33 | instance.udev_unref(udev); 34 | Instance = instance; break; 35 | } 36 | } 37 | catch 38 | { 39 | 40 | } 41 | } 42 | } 43 | 44 | public static NativeMethodsLibudev Instance 45 | { 46 | get; 47 | private set; 48 | } 49 | 50 | public abstract string FriendlyName 51 | { 52 | get; 53 | } 54 | 55 | public abstract IntPtr udev_new(); 56 | 57 | public abstract IntPtr udev_ref(IntPtr udev); 58 | 59 | public abstract void udev_unref(IntPtr udev); 60 | 61 | public abstract IntPtr udev_monitor_new_from_netlink(IntPtr udev, string name); 62 | 63 | public abstract void udev_monitor_unref(IntPtr monitor); 64 | 65 | public abstract int udev_monitor_filter_add_match_subsystem_devtype(IntPtr monitor, string subsystem, string devtype); 66 | 67 | public abstract int udev_monitor_enable_receiving(IntPtr monitor); 68 | 69 | public abstract int udev_monitor_get_fd(IntPtr monitor); 70 | 71 | public abstract IntPtr udev_monitor_receive_device(IntPtr monitor); 72 | 73 | public abstract IntPtr udev_enumerate_new(IntPtr udev); 74 | 75 | public abstract IntPtr udev_enumerate_ref(IntPtr enumerate); 76 | 77 | public abstract void udev_enumerate_unref(IntPtr enumerate); 78 | 79 | public abstract int udev_enumerate_add_match_subsystem(IntPtr enumerate, string subsystem); 80 | 81 | public abstract int udev_enumerate_scan_devices(IntPtr enumerate); 82 | 83 | public abstract IntPtr udev_enumerate_get_list_entry(IntPtr enumerate); 84 | 85 | public abstract IntPtr udev_list_entry_get_next(IntPtr entry); 86 | 87 | public abstract string udev_list_entry_get_name(IntPtr entry); 88 | 89 | public abstract IntPtr udev_device_new_from_syspath(IntPtr udev, string syspath); 90 | 91 | public abstract IntPtr udev_device_ref(IntPtr device); 92 | 93 | public abstract void udev_device_unref(IntPtr device); 94 | 95 | public abstract string udev_device_get_devnode(IntPtr device); 96 | 97 | public abstract IntPtr udev_device_get_parent_with_subsystem_devtype(IntPtr device, string subsystem, string devtype); 98 | 99 | public abstract string udev_device_get_sysattr_value(IntPtr device, string sysattr); 100 | 101 | public abstract int udev_device_get_is_initialized(IntPtr device); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /HidSharp/Platform/MacOS/MacHidManager.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012, 2015, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace HidSharp.Platform.MacOS 23 | { 24 | sealed class MacHidManager : HidManager 25 | { 26 | protected override SystemEvents.EventManager CreateEventManager() 27 | { 28 | return new SystemEvents.MacOSEventManager(); 29 | } 30 | 31 | protected override void Run(Action readyCallback) 32 | { 33 | using (var manager = NativeMethods.IOHIDManagerCreate(IntPtr.Zero).ToCFType()) 34 | { 35 | RunAssert(manager.IsSet, "HidSharp IOHIDManagerCreate failed."); 36 | 37 | using (var matching = NativeMethods.IOServiceMatching("IOHIDDevice").ToCFType()) 38 | { 39 | RunAssert(matching.IsSet, "HidSharp IOServiceMatching failed."); 40 | 41 | var devicesChangedCallback = new NativeMethods.IOHIDDeviceCallback(DevicesChangedCallback); 42 | NativeMethods.IOHIDManagerSetDeviceMatching(manager.Handle, matching.Handle); 43 | NativeMethods.IOHIDManagerRegisterDeviceMatchingCallback(manager.Handle, devicesChangedCallback, IntPtr.Zero); 44 | NativeMethods.IOHIDManagerRegisterDeviceRemovalCallback(manager.Handle, devicesChangedCallback, IntPtr.Zero); 45 | 46 | var runLoop = NativeMethods.CFRunLoopGetCurrent(); 47 | NativeMethods.CFRetain(runLoop); 48 | NativeMethods.IOHIDManagerScheduleWithRunLoop(manager, runLoop, NativeMethods.kCFRunLoopDefaultMode); 49 | try 50 | { 51 | readyCallback(); 52 | NativeMethods.CFRunLoopRun(); 53 | } 54 | finally 55 | { 56 | NativeMethods.IOHIDManagerUnscheduleFromRunLoop(manager, runLoop, NativeMethods.kCFRunLoopDefaultMode); 57 | NativeMethods.CFRelease(runLoop); 58 | } 59 | 60 | GC.KeepAlive(devicesChangedCallback); 61 | } 62 | } 63 | } 64 | 65 | static void DevicesChangedCallback(IntPtr context, NativeMethods.IOReturn result, IntPtr sender, IntPtr device) 66 | { 67 | DeviceList.Local.RaiseChanged(); 68 | } 69 | 70 | object[] GetDeviceKeys(string kind) 71 | { 72 | var paths = new List(); 73 | 74 | var matching = NativeMethods.IOServiceMatching(kind).ToCFType(); // Consumed by IOServiceGetMatchingServices, so DON'T Dispose(). 75 | if (matching.IsSet) 76 | { 77 | int iteratorObj; 78 | if (NativeMethods.IOReturn.Success == NativeMethods.IOServiceGetMatchingServices(0, matching, out iteratorObj)) 79 | { 80 | using (var iterator = iteratorObj.ToIOObject()) 81 | { 82 | while (true) 83 | { 84 | using (var handle = NativeMethods.IOIteratorNext(iterator).ToIOObject()) 85 | { 86 | if (!handle.IsSet) { break; } 87 | 88 | NativeMethods.io_string_t path; 89 | if (NativeMethods.IOReturn.Success == NativeMethods.IORegistryEntryGetPath(handle, "IOService", out path)) 90 | { 91 | paths.Add(path); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | 99 | return paths.Cast().ToArray(); 100 | } 101 | 102 | protected override object[] GetBleDeviceKeys() 103 | { 104 | return new object[0]; 105 | } 106 | 107 | protected override object[] GetHidDeviceKeys() 108 | { 109 | return GetDeviceKeys("IOHIDDevice"); 110 | } 111 | 112 | protected override object[] GetSerialDeviceKeys() 113 | { 114 | return GetDeviceKeys("IOSerialBSDClient"); 115 | } 116 | 117 | protected override bool TryCreateBleDevice(object key, out Device device) 118 | { 119 | throw new NotImplementedException(); 120 | } 121 | 122 | protected override bool TryCreateHidDevice(object key, out Device device) 123 | { 124 | device = MacHidDevice.TryCreate((NativeMethods.io_string_t)key); 125 | return device != null; 126 | } 127 | 128 | protected override bool TryCreateSerialDevice(object key, out Device device) 129 | { 130 | device = MacSerialDevice.TryCreate((NativeMethods.io_string_t)key); 131 | return device != null; 132 | } 133 | 134 | public override string FriendlyName 135 | { 136 | get { return "Mac OS HID"; } 137 | } 138 | 139 | public override bool IsSupported 140 | { 141 | get 142 | { 143 | if (Environment.OSVersion.Platform == PlatformID.Unix) 144 | { 145 | try 146 | { 147 | IntPtr major; NativeMethods.OSErr majorErr = NativeMethods.Gestalt(NativeMethods.OSType.gestaltSystemVersionMajor, out major); 148 | IntPtr minor; NativeMethods.OSErr minorErr = NativeMethods.Gestalt(NativeMethods.OSType.gestaltSystemVersionMinor, out minor); 149 | if (majorErr == NativeMethods.OSErr.noErr && minorErr == NativeMethods.OSErr.noErr) 150 | { 151 | return (long)major >= 10 || ((long)major == 10 && (long)minor >= 6); 152 | } 153 | } 154 | catch 155 | { 156 | 157 | } 158 | } 159 | 160 | return false; 161 | } 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /HidSharp/Platform/MacOS/MacSerialDevice.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Platform.MacOS 21 | { 22 | sealed class MacSerialDevice : SerialDevice 23 | { 24 | NativeMethods.io_string_t _path; 25 | string _fileSystemName; 26 | 27 | protected override DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig) 28 | { 29 | return new MacSerialStream(this); 30 | } 31 | 32 | internal static MacSerialDevice TryCreate(NativeMethods.io_string_t path) 33 | { 34 | var d = new MacSerialDevice() { _path = path }; 35 | 36 | var handle = NativeMethods.IORegistryEntryFromPath(0, ref path).ToIOObject(); 37 | if (!handle.IsSet) { return null; } 38 | 39 | using (handle) 40 | { 41 | d._fileSystemName = NativeMethods.IORegistryEntryGetCFProperty_String(handle, NativeMethods.kIOCalloutDeviceKey); 42 | if (d._fileSystemName == null) { return null; } 43 | } 44 | 45 | return d; 46 | } 47 | 48 | public override string GetFileSystemName() 49 | { 50 | return _fileSystemName; 51 | } 52 | 53 | public override bool HasImplementationDetail(Guid detail) 54 | { 55 | return base.HasImplementationDetail(detail) || detail == ImplementationDetail.MacOS; 56 | } 57 | 58 | public override string DevicePath 59 | { 60 | get { return _path.ToString(); } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /HidSharp/Platform/SysBleStream.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012-2013, 2016, 2018-2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Platform 19 | { 20 | abstract class SysBleStream : Experimental.BleStream 21 | { 22 | internal SysBleStream(Experimental.BleDevice device, Experimental.BleService service) 23 | : base(device, service) 24 | { 25 | 26 | } 27 | 28 | #region Reference Counting 29 | SysRefCountHelper _rch; 30 | 31 | internal void HandleInitAndOpen() 32 | { 33 | _rch.HandleInitAndOpen(); 34 | } 35 | 36 | internal bool HandleClose() 37 | { 38 | return _rch.HandleClose(); 39 | } 40 | 41 | internal bool HandleAcquire() 42 | { 43 | return _rch.HandleAcquire(); 44 | } 45 | 46 | internal void HandleAcquireIfOpenOrFail() 47 | { 48 | _rch.HandleAcquireIfOpenOrFail(); 49 | } 50 | 51 | internal void HandleRelease() 52 | { 53 | if (_rch.HandleRelease()) { HandleFree(); } 54 | } 55 | 56 | internal abstract void HandleFree(); 57 | #endregion 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /HidSharp/Platform/SysHidStream.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012-2013, 2016, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | using System.Threading; 22 | 23 | namespace HidSharp.Platform 24 | { 25 | abstract class SysHidStream : HidStream 26 | { 27 | protected SysHidStream(HidDevice device) 28 | : base(device) 29 | { 30 | 31 | } 32 | 33 | internal class CommonOutputReport 34 | { 35 | public byte[] Bytes; 36 | public bool DoneOK, Feature; 37 | public volatile bool Done; 38 | } 39 | 40 | internal static int GetTimeout(int startTime, int timeout) 41 | { 42 | return Math.Min(timeout, Math.Max(0, startTime + timeout - Environment.TickCount)); 43 | } 44 | 45 | internal void CommonDisconnected(Queue readQueue) 46 | { 47 | lock (readQueue) 48 | { 49 | if (readQueue.Count == 0 || null != readQueue.Peek()) { readQueue.Enqueue(null); Monitor.PulseAll(readQueue); } 50 | } 51 | } 52 | 53 | internal int CommonRead(byte[] buffer, int offset, int count, Queue queue) 54 | { 55 | Throw.If.OutOfRange(buffer, offset, count); 56 | if (count == 0) { return 0; } 57 | 58 | int readTimeout = ReadTimeout; 59 | int startTime = Environment.TickCount; 60 | int timeout; 61 | 62 | HandleAcquireIfOpenOrFail(); 63 | try 64 | { 65 | lock (queue) 66 | { 67 | while (true) 68 | { 69 | if (queue.Count > 0) 70 | { 71 | if (null == queue.Peek()) { throw new IOException("I/O disconnected."); } // Disconnected. 72 | 73 | byte[] packet = queue.Dequeue(); 74 | count = Math.Min(count, packet.Length); 75 | Array.Copy(packet, 0, buffer, offset, count); 76 | return count; 77 | } 78 | 79 | timeout = GetTimeout(startTime, readTimeout); 80 | _rch.ThrowIfClosed(); 81 | if (!Monitor.Wait(queue, timeout)) { throw new TimeoutException(); } 82 | } 83 | } 84 | } 85 | finally 86 | { 87 | HandleRelease(); 88 | } 89 | } 90 | 91 | internal void CommonWrite(byte[] buffer, int offset, int count, 92 | Queue queue, 93 | bool feature, int maxOutputReportLength) 94 | { 95 | Throw.If.OutOfRange(buffer, offset, count); 96 | count = Math.Min(count, maxOutputReportLength); 97 | if (count == 0) { return; } 98 | 99 | int writeTimeout = WriteTimeout; 100 | int startTime = Environment.TickCount; 101 | int timeout; 102 | 103 | HandleAcquireIfOpenOrFail(); 104 | try 105 | { 106 | lock (queue) 107 | { 108 | while (true) 109 | { 110 | if (queue.Count == 0) 111 | { 112 | byte[] packet = new byte[count]; 113 | Array.Copy(buffer, offset, packet, 0, count); 114 | var outputReport = new CommonOutputReport() { Bytes = packet, Feature = feature }; 115 | queue.Enqueue(outputReport); 116 | Monitor.PulseAll(queue); 117 | 118 | while (true) 119 | { 120 | if (outputReport.Done) 121 | { 122 | if (!outputReport.DoneOK) { throw new IOException("I/O output report failed."); } 123 | return; 124 | } 125 | 126 | timeout = GetTimeout(startTime, writeTimeout); 127 | _rch.ThrowIfClosed(); 128 | if (!Monitor.Wait(queue, timeout)) { throw new TimeoutException(); } 129 | } 130 | } 131 | else 132 | { 133 | timeout = GetTimeout(startTime, writeTimeout); 134 | _rch.ThrowIfClosed(); 135 | if (!Monitor.Wait(queue, timeout)) { throw new TimeoutException(); } 136 | } 137 | } 138 | } 139 | } 140 | finally 141 | { 142 | HandleRelease(); 143 | } 144 | } 145 | 146 | public sealed override int ReadTimeout 147 | { 148 | get; 149 | set; 150 | } 151 | 152 | public sealed override int WriteTimeout 153 | { 154 | get; 155 | set; 156 | } 157 | 158 | #region Reference Counting 159 | SysRefCountHelper _rch; 160 | 161 | internal void HandleInitAndOpen() 162 | { 163 | _rch.HandleInitAndOpen(); 164 | } 165 | 166 | internal bool HandleClose() 167 | { 168 | return _rch.HandleClose(); 169 | } 170 | 171 | internal bool HandleAcquire() 172 | { 173 | return _rch.HandleAcquire(); 174 | } 175 | 176 | internal void HandleAcquireIfOpenOrFail() 177 | { 178 | _rch.HandleAcquireIfOpenOrFail(); 179 | } 180 | 181 | internal void HandleRelease() 182 | { 183 | if (_rch.HandleRelease()) { HandleFree(); } 184 | } 185 | 186 | internal abstract void HandleFree(); 187 | #endregion 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /HidSharp/Platform/SysRefCountHelper.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012-2013, 2016, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | using System.Text; 22 | using System.Threading; 23 | 24 | namespace HidSharp.Platform 25 | { 26 | struct SysRefCountHelper 27 | { 28 | int _opened, _closed; 29 | int _refCount; 30 | 31 | internal void HandleInitAndOpen() 32 | { 33 | _opened = 1; _refCount = 1; 34 | } 35 | 36 | internal bool HandleClose() 37 | { 38 | return 0 == Interlocked.CompareExchange(ref _closed, 1, 0) && _opened != 0; 39 | } 40 | 41 | internal bool HandleAcquire() 42 | { 43 | while (true) 44 | { 45 | int refCount = _refCount; 46 | if (refCount == 0) { return false; } 47 | 48 | if (refCount == Interlocked.CompareExchange 49 | (ref _refCount, refCount + 1, refCount)) 50 | { 51 | return true; 52 | } 53 | } 54 | } 55 | 56 | internal void HandleAcquireIfOpenOrFail() 57 | { 58 | if (_closed != 0 || !HandleAcquire()) { throw ExceptionForClosed(); } 59 | } 60 | 61 | internal bool HandleRelease() 62 | { 63 | if (0 == Interlocked.Decrement(ref _refCount)) 64 | { 65 | if (_opened != 0) { return true; } 66 | } 67 | 68 | return false; 69 | } 70 | 71 | internal void ThrowIfClosed() 72 | { 73 | if (_closed != 0) { throw ExceptionForClosed(); } 74 | } 75 | 76 | static Exception ExceptionForClosed() 77 | { 78 | return CommonException.CreateClosedException(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /HidSharp/Platform/SysSerialStream.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | using System.Threading; 22 | 23 | namespace HidSharp.Platform 24 | { 25 | abstract class SysSerialStream : SerialStream 26 | { 27 | protected SysSerialStream(SerialDevice device) 28 | : base(device) 29 | { 30 | 31 | } 32 | 33 | #region Reference Counting 34 | int _opened, _closed; 35 | int _refCount; 36 | 37 | internal void HandleInitAndOpen() 38 | { 39 | _opened = 1; _refCount = 1; 40 | } 41 | 42 | internal bool HandleClose() 43 | { 44 | return 0 == Interlocked.CompareExchange(ref _closed, 1, 0) && _opened != 0; 45 | } 46 | 47 | internal bool HandleAcquire() 48 | { 49 | while (true) 50 | { 51 | int refCount = _refCount; 52 | if (refCount == 0) { return false; } 53 | 54 | if (refCount == Interlocked.CompareExchange 55 | (ref _refCount, refCount + 1, refCount)) 56 | { 57 | return true; 58 | } 59 | } 60 | } 61 | 62 | internal void HandleAcquireIfOpenOrFail() 63 | { 64 | if (_closed != 0 || !HandleAcquire()) { throw ExceptionForClosed(); } 65 | } 66 | 67 | internal void HandleRelease() 68 | { 69 | if (0 == Interlocked.Decrement(ref _refCount)) 70 | { 71 | if (_opened != 0) { HandleFree(); } 72 | } 73 | } 74 | 75 | static Exception ExceptionForClosed() 76 | { 77 | return CommonException.CreateClosedException(); 78 | } 79 | 80 | internal abstract void HandleFree(); 81 | #endregion 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /HidSharp/Platform/Unsupported/UnsupportedHidManager.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Platform.Unsupported 21 | { 22 | sealed class UnsupportedHidManager : HidManager 23 | { 24 | protected override object[] GetBleDeviceKeys() 25 | { 26 | return new object[0]; 27 | } 28 | 29 | protected override object[] GetHidDeviceKeys() 30 | { 31 | return new object[0]; 32 | } 33 | 34 | protected override object[] GetSerialDeviceKeys() 35 | { 36 | return new object[0]; 37 | } 38 | 39 | protected override bool TryCreateBleDevice(object key, out Device device) 40 | { 41 | throw new NotImplementedException(); 42 | } 43 | 44 | protected override bool TryCreateHidDevice(object key, out Device device) 45 | { 46 | throw new NotImplementedException(); 47 | } 48 | 49 | protected override bool TryCreateSerialDevice(object key, out Device device) 50 | { 51 | throw new NotImplementedException(); 52 | } 53 | 54 | public override string FriendlyName 55 | { 56 | get { return "Platform Not Supported"; } 57 | } 58 | 59 | public override bool IsSupported 60 | { 61 | get { return true; } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /HidSharp/Platform/Utf8Marshaler.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2012 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Reflection; 21 | using System.Runtime.InteropServices; 22 | using System.Text; 23 | 24 | namespace HidSharp.Platform 25 | { 26 | sealed class Utf8Marshaler : ICustomMarshaler 27 | { 28 | [ThreadStatic] 29 | static HashSet _allocations; // Workaround for Mono bug 4722. 30 | 31 | static HashSet GetAllocations() 32 | { 33 | if (_allocations == null) { _allocations = new HashSet(); } 34 | return _allocations; 35 | } 36 | 37 | public void CleanUpManagedData(object obj) 38 | { 39 | 40 | } 41 | 42 | public void CleanUpNativeData(IntPtr ptr) 43 | { 44 | var allocations = GetAllocations(); 45 | if (IntPtr.Zero == ptr || !allocations.Contains(ptr)) { return; } 46 | Marshal.FreeHGlobal(ptr); allocations.Remove(ptr); 47 | } 48 | 49 | public int GetNativeDataSize() 50 | { 51 | return -1; 52 | } 53 | 54 | public IntPtr MarshalManagedToNative(object obj) 55 | { 56 | string str = obj as string; 57 | if (str == null) { return IntPtr.Zero; } 58 | 59 | byte[] bytes = Encoding.UTF8.GetBytes(str); 60 | IntPtr ptr = Marshal.AllocHGlobal(bytes.Length + 1); 61 | Marshal.Copy(bytes, 0, ptr, bytes.Length); 62 | Marshal.WriteByte(ptr, bytes.Length, 0); 63 | 64 | var allocations = GetAllocations(); 65 | allocations.Add(ptr); return ptr; 66 | } 67 | 68 | public object MarshalNativeToManaged(IntPtr ptr) 69 | { 70 | if (ptr == IntPtr.Zero) { return null; } 71 | 72 | int length; 73 | for (length = 0; Marshal.ReadByte(ptr, length) != 0; length++) ; 74 | 75 | byte[] bytes = new byte[length]; 76 | Marshal.Copy(ptr, bytes, 0, bytes.Length); 77 | string str = Encoding.UTF8.GetString(bytes); 78 | return str; 79 | } 80 | 81 | // This method needs to keep its original name. 82 | [Obfuscation(Exclude = true)] 83 | public static ICustomMarshaler GetInstance(string cookie) 84 | { 85 | return new Utf8Marshaler(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /HidSharp/Platform/Windows/WinBleCharacteristic.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using HidSharp.Experimental; 20 | 21 | namespace HidSharp.Platform.Windows 22 | { 23 | sealed class WinBleCharacteristic : Experimental.BleCharacteristic 24 | { 25 | internal NativeMethods.BTH_LE_GATT_CHARACTERISTIC NativeData; 26 | 27 | internal WinBleDescriptor[] _characteristicDescriptors; 28 | BleCharacteristicProperties _properties; 29 | 30 | public WinBleCharacteristic(NativeMethods.BTH_LE_GATT_CHARACTERISTIC nativeData) 31 | { 32 | NativeData = nativeData; 33 | 34 | _properties = (nativeData.IsBroadcastable != 0 ? BleCharacteristicProperties.Broadcast : 0) 35 | | (nativeData.IsReadable != 0 ? BleCharacteristicProperties.Read : 0) 36 | | (nativeData.IsWritableWithoutResponse != 0 ? BleCharacteristicProperties.WriteWithoutResponse : 0) 37 | | (nativeData.IsWritable != 0 ? BleCharacteristicProperties.Write : 0) 38 | | (nativeData.IsNotifiable != 0 ? BleCharacteristicProperties.Notify : 0) 39 | | (nativeData.IsIndicatable != 0 ? BleCharacteristicProperties.Indicate : 0) 40 | | (nativeData.IsSignedWritable != 0 ? BleCharacteristicProperties.SignedWrite : 0) 41 | | (nativeData.HasExtendedProperties != 0 ? BleCharacteristicProperties.ExtendedProperties : 0) 42 | ; 43 | } 44 | 45 | public override BleDescriptor[] GetDescriptors() 46 | { 47 | return (BleDescriptor[])_characteristicDescriptors.Clone(); 48 | } 49 | 50 | public override BleUuid Uuid 51 | { 52 | get { return NativeData.CharacteristicUuid.ToGuid(); } 53 | } 54 | 55 | public override BleCharacteristicProperties Properties 56 | { 57 | get { return _properties; } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /HidSharp/Platform/Windows/WinBleDescriptor.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using HidSharp.Experimental; 20 | 21 | namespace HidSharp.Platform.Windows 22 | { 23 | sealed class WinBleDescriptor : BleDescriptor 24 | { 25 | internal NativeMethods.BTH_LE_GATT_DESCRIPTOR NativeData; 26 | 27 | public WinBleDescriptor(NativeMethods.BTH_LE_GATT_DESCRIPTOR nativeData) 28 | { 29 | NativeData = nativeData; 30 | } 31 | 32 | public override BleUuid Uuid 33 | { 34 | get { return NativeData.DescriptorUuid.ToGuid(); } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /HidSharp/Platform/Windows/WinBleService.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | using HidSharp.Experimental; 20 | 21 | namespace HidSharp.Platform.Windows 22 | { 23 | sealed class WinBleService : BleService 24 | { 25 | internal NativeMethods.BTH_LE_GATT_SERVICE NativeData; 26 | 27 | WinBleCharacteristic[] _characteristics; 28 | WinBleDevice _device; 29 | object _syncObject; 30 | 31 | public WinBleService(WinBleDevice device, NativeMethods.BTH_LE_GATT_SERVICE nativeData) 32 | { 33 | _device = device; NativeData = nativeData; _syncObject = new object(); 34 | } 35 | 36 | public override BleCharacteristic[] GetCharacteristics() 37 | { 38 | lock (_syncObject) 39 | { 40 | if (_characteristics == null) 41 | { 42 | if (!_device.TryOpenToGetInfo(handle => 43 | { 44 | var nativeCharacteristics = NativeMethods.BluetoothGATTGetCharacteristics(handle, ref NativeData); 45 | if (nativeCharacteristics == null) { return false; } 46 | 47 | var characteristics = new List(); 48 | foreach (var nativeCharacteristic in nativeCharacteristics) 49 | { 50 | var characteristic = new WinBleCharacteristic(nativeCharacteristic); 51 | characteristics.Add(characteristic); 52 | 53 | var nativeDescriptors = NativeMethods.BluetoothGATTGetDescriptors(handle, ref characteristic.NativeData); 54 | if (nativeDescriptors == null) { return false; } 55 | 56 | var descriptors = new List(); 57 | foreach (var nativeDescriptor in nativeDescriptors) 58 | { 59 | var descriptor = new WinBleDescriptor(nativeDescriptor); 60 | descriptors.Add(descriptor); 61 | } 62 | 63 | characteristic._characteristicDescriptors = descriptors.ToArray(); 64 | } 65 | 66 | _characteristics = characteristics.ToArray(); 67 | return true; 68 | })) 69 | { 70 | throw DeviceException.CreateIOException(_device, "BLE service information could not be retrieved."); 71 | } 72 | } 73 | } 74 | 75 | return (BleCharacteristic[])_characteristics.Clone(); 76 | } 77 | 78 | public override BleDevice Device 79 | { 80 | get { return _device; } 81 | } 82 | 83 | public override BleUuid Uuid 84 | { 85 | get { return NativeData.ServiceUuid.ToGuid(); } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /HidSharp/Platform/Windows/WinHidDevice.ReportDescriptorBuilder.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | using System.Linq; 22 | using HidSharp.Reports; 23 | using HidSharp.Reports.Encodings; 24 | 25 | namespace HidSharp.Platform.Windows 26 | { 27 | partial class WinHidDevice 28 | { 29 | sealed class ReportDescriptorBuilder 30 | { 31 | Dictionary _globals; 32 | List _items; 33 | 34 | public ReportDescriptorBuilder() 35 | { 36 | _globals = new Dictionary(); 37 | _items = new List(); 38 | } 39 | 40 | public void AddGlobalItem(GlobalItemTag globalItemTag, uint dataValue) 41 | { 42 | uint oldDataValue; 43 | if (_globals.TryGetValue(globalItemTag, out oldDataValue) && oldDataValue == dataValue) { return; } 44 | _globals[globalItemTag] = dataValue; 45 | 46 | var item = new EncodedItem() { ItemType = ItemType.Global, TagForGlobal = globalItemTag, DataValue = dataValue }; 47 | _items.Add(item); 48 | } 49 | 50 | public void AddGlobalItemSigned(GlobalItemTag globalItemTag, int dataValue) 51 | { 52 | uint oldDataValue; 53 | if (_globals.TryGetValue(globalItemTag, out oldDataValue) && oldDataValue == (uint)dataValue) { return; } 54 | _globals[globalItemTag] = (uint)dataValue; 55 | 56 | var item = new EncodedItem() { ItemType = ItemType.Global, TagForGlobal = globalItemTag, DataValueSigned = dataValue }; 57 | _items.Add(item); 58 | } 59 | 60 | public void AddLocalItem(LocalItemTag localItemTag, uint dataValue) 61 | { 62 | _items.Add(new EncodedItem() { ItemType = ItemType.Local, TagForLocal = localItemTag, DataValue = dataValue }); 63 | } 64 | 65 | public void AddMainItem(MainItemTag mainItemTag, uint dataValue) 66 | { 67 | _items.Add(new EncodedItem() { ItemType = ItemType.Main, TagForMain = mainItemTag, DataValue = dataValue }); 68 | } 69 | 70 | public byte[] GetReportDescriptor() 71 | { 72 | var bytes = new List(); 73 | EncodedItem.EncodeItems(_items, bytes); 74 | return bytes.ToArray(); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /HidSharp/Platform/Windows/WinSerialDevice.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017-2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Platform.Windows 19 | { 20 | sealed class WinSerialDevice : SerialDevice 21 | { 22 | string _path; 23 | string _fileSystemName; 24 | string _friendlyName; 25 | 26 | protected override DeviceStream OpenDeviceDirectly(OpenConfiguration openConfig) 27 | { 28 | var stream = new WinSerialStream(this); 29 | stream.Init(DevicePath); 30 | return stream; 31 | } 32 | 33 | internal static WinSerialDevice TryCreate(string portName, string fileSystemName, string friendlyName) 34 | { 35 | return new WinSerialDevice() { _path = portName, _fileSystemName = fileSystemName, _friendlyName = friendlyName }; 36 | } 37 | 38 | public override string GetFileSystemName() 39 | { 40 | return _fileSystemName; 41 | } 42 | 43 | public override string GetFriendlyName() 44 | { 45 | return _friendlyName; 46 | } 47 | 48 | public override string DevicePath 49 | { 50 | get { return _path; } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /HidSharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: ComVisible(false)] 5 | [assembly: Guid("1b874372-4c6c-4acb-9f4a-906f6738cff9")] 6 | -------------------------------------------------------------------------------- /HidSharp/Reports/DataConvert.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Reports 21 | { 22 | public static class DataConvert 23 | { 24 | public static int LogicalFromPhysical(DataItem item, double physicalValue) 25 | { 26 | Throw.If.Null(item); 27 | if (item.IsArray) { return (physicalValue > 0) ? 1 : 0; } 28 | return LogicalFromCustom(item, physicalValue, item.PhysicalMinimum, item.PhysicalMaximum); 29 | } 30 | 31 | public static int LogicalFromCustom(DataItem item, double physicalValue, double minimum, double maximum) 32 | { 33 | return Math.Max(item.LogicalMinimum, Math.Min(item.LogicalMaximum, (int)Math.Round((physicalValue - minimum) * item.LogicalRange / (maximum - minimum)))); 34 | } 35 | 36 | public static int LogicalFromRaw(DataItem item, uint value) 37 | { 38 | Throw.If.Null(item); 39 | uint signBit = 1u << (item.ElementBits - 1), mask = signBit - 1; 40 | return (value & signBit) != 0 ? (int)(value | ~mask) : (int)value; 41 | } 42 | 43 | public static int DataIndexFromLogical(DataItem item, int logicalValue) 44 | { 45 | Throw.If.Null(item); 46 | if (!item.IsArray) { throw new ArgumentException("Data item is not an array.", "item"); } 47 | return IsLogicalOutOfRange(item, logicalValue) ? -1 : logicalValue - item.LogicalMinimum; 48 | } 49 | 50 | public static double PhysicalFromLogical(DataItem item, int logicalValue) 51 | { 52 | Throw.If.Null(item); 53 | if (item.IsArray) { return (logicalValue > 0) ? 1 : 0; } 54 | return CustomFromLogical(item, logicalValue, item.PhysicalMinimum, item.PhysicalRange); 55 | } 56 | 57 | public static double CustomFromLogical(DataItem item, int logicalValue, double minimum, double maximum) 58 | { 59 | if (IsLogicalOutOfRange(item, logicalValue)) { return double.NaN; } 60 | return minimum + (logicalValue - item.LogicalMinimum) * (maximum - minimum) / item.LogicalRange; 61 | } 62 | 63 | public static uint RawFromLogical(DataItem item, int value) 64 | { 65 | Throw.If.Null(item); 66 | uint usValue = (uint)value; 67 | uint signBit = 1u << (item.ElementBits - 1), mask = signBit - 1; 68 | return (usValue & mask) | (value < 0 ? signBit : 0); 69 | } 70 | 71 | public static bool IsLogicalOutOfRange(DataItem item, int logicalValue) 72 | { 73 | Throw.If.Null(item); 74 | return item.IsLogicalSigned 75 | ? (logicalValue < item.LogicalMinimum || logicalValue > item.LogicalMaximum) 76 | : ((uint)logicalValue < (uint)item.LogicalMinimum || (uint)logicalValue > (uint)item.LogicalMaximum) 77 | ; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /HidSharp/Reports/DataItemFlags.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Reports 21 | { 22 | [Flags] 23 | public enum DataItemFlags : uint 24 | { 25 | /// 26 | /// No flags are set. 27 | /// 28 | None = 0, 29 | 30 | /// 31 | /// Constant values cannot be changed. 32 | /// 33 | Constant = 1 << 0, 34 | 35 | /// 36 | /// Each variable field corresponds to a particular value. 37 | /// The alternative is an array, where each field specifies an index. 38 | /// For example, with eight buttons, a variable field would have eight bits. 39 | /// An array would have an index of which button is pressed. 40 | /// 41 | Variable = 1 << 1, 42 | 43 | /// 44 | /// Mouse motion is in relative coordinates. 45 | /// Most sensors -- joysticks, accelerometers, etc. -- output absolute coordinates. 46 | /// 47 | Relative = 1 << 2, 48 | 49 | /// 50 | /// The value wraps around in a continuous manner. 51 | /// 52 | Wrap = 1 << 3, 53 | 54 | Nonlinear = 1 << 4, 55 | 56 | NoPreferred = 1 << 5, 57 | 58 | NullState = 1 << 6, 59 | 60 | Volatile = 1 << 7, 61 | 62 | BufferedBytes = 1 << 8 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /HidSharp/Reports/DataValue.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | 21 | namespace HidSharp.Reports 22 | { 23 | public struct DataValue 24 | { 25 | int _logicalValue; 26 | 27 | public int GetLogicalValue() 28 | { 29 | return _logicalValue; 30 | } 31 | 32 | public void SetLogicalValue(int logicalValue) 33 | { 34 | _logicalValue = logicalValue; 35 | } 36 | 37 | public double GetFractionalValue() 38 | { 39 | return GetScaledValue(0, 1); 40 | } 41 | 42 | public double GetScaledValue(double minimum, double maximum) 43 | { 44 | return DataConvert.CustomFromLogical(DataItem, GetLogicalValue(), minimum, maximum); 45 | } 46 | 47 | public double GetPhysicalValue() 48 | { 49 | return DataConvert.PhysicalFromLogical(DataItem, GetLogicalValue()); 50 | } 51 | 52 | public DataItem DataItem 53 | { 54 | get; 55 | set; 56 | } 57 | 58 | public int DataIndex 59 | { 60 | get; 61 | set; 62 | } 63 | 64 | public bool IsNull 65 | { 66 | get { return !IsValid || (DataItem.IsVariable && DataConvert.IsLogicalOutOfRange(DataItem, GetLogicalValue())); } 67 | } 68 | 69 | public bool IsValid 70 | { 71 | get { return DataItem != null; } 72 | } 73 | 74 | public Report Report 75 | { 76 | get { return IsValid ? DataItem.Report : null; } 77 | } 78 | 79 | public IEnumerable Designators 80 | { 81 | get { return IsValid ? DataItem.Designators.GetValuesFromIndex(DataIndex) : Enumerable.Empty(); } 82 | } 83 | 84 | public IEnumerable Strings 85 | { 86 | get { return IsValid ? DataItem.Strings.GetValuesFromIndex(DataIndex) : Enumerable.Empty(); } 87 | } 88 | 89 | public IEnumerable Usages 90 | { 91 | get { return IsValid ? DataItem.Usages.GetValuesFromIndex(DataIndex) : Enumerable.Empty(); } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /HidSharp/Reports/DescriptorCollectionItem.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Collections.ObjectModel; 21 | using System.Diagnostics; 22 | using HidSharp.Reports.Encodings; 23 | 24 | namespace HidSharp.Reports 25 | { 26 | public class DescriptorCollectionItem : DescriptorItem 27 | { 28 | ReportCollectionItemChildren _children; 29 | 30 | public DescriptorCollectionItem() 31 | { 32 | _children = new ReportCollectionItemChildren(this); 33 | } 34 | 35 | public override IList ChildItems 36 | { 37 | get { return _children; } 38 | } 39 | 40 | public CollectionType CollectionType 41 | { 42 | get; 43 | set; 44 | } 45 | 46 | #region ReportCollectionItemChildren 47 | sealed class ReportCollectionItemChildren : Collection 48 | { 49 | DescriptorCollectionItem _item; 50 | 51 | public ReportCollectionItemChildren(DescriptorCollectionItem item) 52 | { 53 | Debug.Assert(item != null); 54 | _item = item; 55 | } 56 | 57 | protected override void ClearItems() 58 | { 59 | foreach (var item in this) { item.ParentItem = null; } 60 | base.ClearItems(); 61 | } 62 | 63 | protected override void InsertItem(int index, DescriptorItem item) 64 | { 65 | Throw.If.Null(item).False(item.ParentItem == null); 66 | item.ParentItem = _item; 67 | base.InsertItem(index, item); 68 | } 69 | 70 | protected override void RemoveItem(int index) 71 | { 72 | this[index].ParentItem = null; 73 | base.RemoveItem(index); 74 | } 75 | 76 | protected override void SetItem(int index, DescriptorItem item) 77 | { 78 | throw new NotImplementedException(); 79 | } 80 | } 81 | #endregion 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /HidSharp/Reports/DescriptorItem.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | using System.Collections.ObjectModel; 20 | 21 | namespace HidSharp.Reports 22 | { 23 | public class DescriptorItem 24 | { 25 | static readonly IList _noChildren = new ReadOnlyCollection(new DescriptorItem[0]); 26 | 27 | Indexes _designator, _string, _usage; 28 | 29 | public DescriptorItem() 30 | { 31 | 32 | } 33 | 34 | public virtual IList ChildItems 35 | { 36 | get { return _noChildren; } 37 | } 38 | 39 | public DescriptorCollectionItem ParentItem 40 | { 41 | get; 42 | internal set; 43 | } 44 | 45 | public Indexes Designators 46 | { 47 | get { return _designator ?? Indexes.Unset; } 48 | set { _designator = value; } 49 | } 50 | 51 | public Indexes Strings 52 | { 53 | get { return _string ?? Indexes.Unset; } 54 | set { _string = value; } 55 | } 56 | 57 | public Indexes Usages 58 | { 59 | get { return _usage ?? Indexes.Unset; } 60 | set { _usage = value; } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /HidSharp/Reports/DeviceItem.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Collections.ObjectModel; 21 | using System.Diagnostics; 22 | using System.Linq; 23 | 24 | namespace HidSharp.Reports 25 | { 26 | public class DeviceItem : DescriptorCollectionItem 27 | { 28 | ReportCollectionItemReports _reports; 29 | 30 | public DeviceItem() 31 | { 32 | _reports = new ReportCollectionItemReports(this); 33 | } 34 | 35 | /// 36 | /// Creates a appropriate for parsing reports for this device item. 37 | /// 38 | /// The new . 39 | /// 40 | /// Pair this with a for the . 41 | /// 42 | public Input.DeviceItemInputParser CreateDeviceItemInputParser() 43 | { 44 | return new Input.DeviceItemInputParser(this); 45 | } 46 | 47 | public IList Reports 48 | { 49 | get { return _reports; } 50 | } 51 | 52 | public IEnumerable InputReports 53 | { 54 | get { return Reports.Where(report => report.ReportType == ReportType.Input); } 55 | } 56 | 57 | public IEnumerable OutputReports 58 | { 59 | get { return Reports.Where(report => report.ReportType == ReportType.Output); } 60 | } 61 | 62 | public IEnumerable FeatureReports 63 | { 64 | get { return Reports.Where(report => report.ReportType == ReportType.Feature); } 65 | } 66 | 67 | #region ReportCollectionItemReports 68 | sealed class ReportCollectionItemReports : Collection 69 | { 70 | DeviceItem _item; 71 | 72 | public ReportCollectionItemReports(DeviceItem item) 73 | { 74 | Debug.Assert(item != null); 75 | _item = item; 76 | } 77 | 78 | protected override void ClearItems() 79 | { 80 | foreach (var item in this) { item.DeviceItem = null; } 81 | base.ClearItems(); 82 | } 83 | 84 | protected override void InsertItem(int index, Report item) 85 | { 86 | Throw.If.Null(item).False(item.DeviceItem == null); 87 | item.DeviceItem = _item; 88 | base.InsertItem(index, item); 89 | } 90 | 91 | protected override void RemoveItem(int index) 92 | { 93 | this[index].DeviceItem = null; 94 | base.RemoveItem(index); 95 | } 96 | 97 | protected override void SetItem(int index, Report item) 98 | { 99 | throw new NotImplementedException(); 100 | } 101 | } 102 | #endregion 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /HidSharp/Reports/Encodings/CollectionType.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Encodings 19 | { 20 | public enum CollectionType : byte 21 | { 22 | Physical = 0, 23 | Application, 24 | Logical, 25 | Report, 26 | NamedArray, 27 | UsageSwitch, 28 | UsageModifier 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /HidSharp/Reports/Encodings/EncodedItem.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | 21 | namespace HidSharp.Reports.Encodings 22 | { 23 | public class EncodedItem 24 | { 25 | public EncodedItem() 26 | { 27 | Data = new List(); 28 | } 29 | 30 | public override string ToString() 31 | { 32 | switch (ItemType) 33 | { 34 | case ItemType.Global: return string.Format("{0} {1}", TagForGlobal, DataValue); 35 | case ItemType.Local: return string.Format("{0} {1}", TagForLocal, DataValue); 36 | case ItemType.Main: return string.Format("{0} {1}", TagForMain, DataValue); 37 | default: return Tag.ToString(); 38 | } 39 | } 40 | 41 | public void Reset() 42 | { 43 | Data.Clear(); Tag = 0; ItemType = ItemType.Main; 44 | } 45 | 46 | byte DataAt(int index) 47 | { 48 | return index >= 0 && index < Data.Count ? Data[index] : (byte)0; 49 | } 50 | 51 | static byte GetByte(IList buffer, ref int offset, ref int count) 52 | { 53 | if (count <= 0) { return 0; } else { count--; } 54 | return offset >= 0 && offset < buffer.Count ? buffer[offset++] : (byte)0; 55 | } 56 | 57 | public int Decode(IList buffer, int offset, int count) 58 | { 59 | Throw.If.OutOfRange(buffer, offset, count); 60 | 61 | Reset(); int startCount = count; 62 | byte header = GetByte(buffer, ref offset, ref count); 63 | 64 | int size = header & 0x3; if (size == 3) { size = 4; } 65 | ItemType = (ItemType)((header >> 2) & 0x3); Tag = (byte)(header >> 4); 66 | for (int i = 0; i < size; i++) { Data.Add(GetByte(buffer, ref offset, ref count)); } 67 | return startCount - count; 68 | } 69 | 70 | public static IEnumerable DecodeItems(IList buffer, int offset, int count) 71 | { 72 | Throw.If.OutOfRange(buffer, offset, count); 73 | 74 | while (count > 0) 75 | { 76 | EncodedItem item = new EncodedItem(); 77 | int bytes = item.Decode(buffer, offset, count); 78 | offset += bytes; count -= bytes; 79 | yield return item; 80 | } 81 | } 82 | 83 | /* 84 | // TODO: What was I intending to use this for? 85 | public static IEnumerable DecodeHIDDT(IList buffer, int offset, int count) 86 | { 87 | Throw.If.OutOfRange(buffer, offset, count); 88 | 89 | while (count > 34) 90 | { 91 | EncodedItem item = new EncodedItem(); 92 | int bytes = item.Decode(buffer, offset + 34, count - 34); 93 | offset += 10; count -= 10; 94 | yield return item; 95 | } 96 | } 97 | */ 98 | 99 | public void Encode(IList buffer) 100 | { 101 | Throw.If.Null(buffer, "buffer"); 102 | 103 | if (buffer == null) { throw new ArgumentNullException("buffer"); } 104 | if (!IsShortTag) { return; } // TODO 105 | 106 | int size = DataSize; 107 | buffer.Add((byte)((size == 4 ? (byte)3 : size) | (byte)ItemType << 2 | Tag << 4)); 108 | foreach (byte @byte in Data) { buffer.Add(@byte); } 109 | } 110 | 111 | public static void EncodeItems(IEnumerable items, IList buffer) 112 | { 113 | Throw.If.Null(buffer, "buffer").Null(items, "items"); 114 | foreach (EncodedItem item in items) { item.Encode(buffer); } 115 | } 116 | 117 | public IList Data 118 | { 119 | get; 120 | private set; 121 | } 122 | 123 | public int DataSize 124 | { 125 | get { return IsShortTag ? Data.Count : 0; } 126 | } 127 | 128 | public uint DataValue 129 | { 130 | get 131 | { 132 | if (!IsShortTag) { return 0; } 133 | return (uint)(DataAt(0) | DataAt(1) << 8 | DataAt(2) << 16 | DataAt(3) << 24); 134 | } 135 | 136 | set 137 | { 138 | Data.Clear(); 139 | Data.Add((byte)value); 140 | if (value > 0xff) { Data.Add((byte)(value >> 8)); } 141 | if (value > 0xffff) { Data.Add((byte)(value >> 16)); Data.Add((byte)(value >> 24)); } 142 | } 143 | } 144 | 145 | public int DataValueSigned 146 | { 147 | get 148 | { 149 | if (!IsShortTag) { return 0; } 150 | return Data.Count == 4 ? (int)DataValue : 151 | Data.Count == 2 ? (short)DataValue : 152 | Data.Count == 1 ? (sbyte)DataValue : (sbyte)0; 153 | } 154 | 155 | set 156 | { 157 | if (value == 0) 158 | { DataValue = (uint)value; } 159 | else if (value >= sbyte.MinValue && value <= sbyte.MaxValue) 160 | { DataValue = (uint)(sbyte)value; if (value < 0) { Data.Add(0); } } 161 | else if (value >= short.MinValue && value <= short.MaxValue) 162 | { DataValue = (uint)(short)value; if (value < 0) { Data.Add(0); Data.Add(0); } } 163 | else 164 | { DataValue = (uint)value; } 165 | } 166 | } 167 | 168 | public byte Tag 169 | { 170 | get; 171 | set; 172 | } 173 | 174 | public GlobalItemTag TagForGlobal 175 | { 176 | get { return (GlobalItemTag)Tag; } 177 | set { Tag = (byte)value; } 178 | } 179 | 180 | public LocalItemTag TagForLocal 181 | { 182 | get { return (LocalItemTag)Tag; } 183 | set { Tag = (byte)value; } 184 | } 185 | 186 | public MainItemTag TagForMain 187 | { 188 | get { return (MainItemTag)Tag; } 189 | set { Tag = (byte)value; } 190 | } 191 | 192 | public ItemType ItemType 193 | { 194 | get; 195 | set; 196 | } 197 | 198 | public bool IsShortTag 199 | { 200 | get { return !IsLongTag && (Data.Count == 0 || Data.Count == 1 || Data.Count == 2 || Data.Count == 4); } 201 | } 202 | 203 | public bool IsLongTag 204 | { 205 | get { return Tag == 15 && ItemType == ItemType.Reserved && Data.Count >= 2; } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /HidSharp/Reports/Encodings/GlobalItemTag.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Encodings 19 | { 20 | public enum GlobalItemTag : byte 21 | { 22 | UsagePage = 0, 23 | LogicalMinimum, 24 | LogicalMaximum, 25 | PhysicalMinimum, 26 | PhysicalMaximum, 27 | UnitExponent, 28 | Unit, 29 | ReportSize, 30 | ReportID, 31 | ReportCount, 32 | Push, 33 | Pop 34 | } 35 | } -------------------------------------------------------------------------------- /HidSharp/Reports/Encodings/ItemType.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Encodings 19 | { 20 | /// 21 | /// Describes the manner in which an item affects the descriptor. 22 | /// 23 | public enum ItemType : byte 24 | { 25 | /// 26 | /// Main items determine the report being described. 27 | /// For example, a main item switches between Input and Output reports. 28 | /// 29 | Main = 0, 30 | 31 | /// 32 | /// Global items affect all reports later in the descriptor. 33 | /// 34 | Global, 35 | 36 | /// 37 | /// Local items only affect the current report. 38 | /// 39 | Local, 40 | 41 | /// 42 | /// Long items use this type. 43 | /// 44 | Reserved 45 | } 46 | } -------------------------------------------------------------------------------- /HidSharp/Reports/Encodings/LocalItemTag.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Encodings 19 | { 20 | public enum LocalItemTag : byte 21 | { 22 | Usage = 0, 23 | UsageMinimum, 24 | UsageMaximum, 25 | DesignatorIndex, 26 | DesignatorMinimum, 27 | DesignatorMaximum, 28 | StringIndex = 7, 29 | StringMinimum, 30 | StringMaximum, 31 | Delimiter 32 | } 33 | } -------------------------------------------------------------------------------- /HidSharp/Reports/Encodings/MainItemTag.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Encodings 19 | { 20 | public enum MainItemTag : byte 21 | { 22 | Input = 8, 23 | Output, 24 | Collection, 25 | Feature, 26 | EndCollection 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /HidSharp/Reports/ExpectedUsageType.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports 19 | { 20 | public enum ExpectedUsageType 21 | { 22 | /// 23 | /// Level-triggered. A momentary button. 0 indicates not pressed, 1 indicates pressed. 24 | /// 25 | PushButton = 1, 26 | 27 | /// 28 | /// Level-triggered. Toggle buttons maintain their state. 0 indicates not pressed, 1 indicates pressed. 29 | /// 30 | ToggleButton, 31 | 32 | /// 33 | /// Edge-triggered. A 0-to-1 transition should activate the one-shot function. 34 | /// 35 | OneShot, 36 | 37 | /// 38 | /// Edge-triggered. Each report of -1 goes down. Each report of 1 goes up. 39 | /// 40 | UpDown 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /HidSharp/Reports/IndexList.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace HidSharp.Reports 21 | { 22 | public class IndexList : Indexes 23 | { 24 | public IndexList() 25 | { 26 | Indices = new List>(); 27 | } 28 | 29 | public override bool TryGetIndexFromValue(uint value, out int index) 30 | { 31 | for (int i = 0; i < Indices.Count; i ++) 32 | { 33 | foreach (uint thisValue in Indices[i]) 34 | { 35 | if (thisValue == value) { index = i; return true; } 36 | } 37 | } 38 | 39 | return base.TryGetIndexFromValue(value, out index); 40 | } 41 | 42 | public override IEnumerable GetValuesFromIndex(int index) 43 | { 44 | if (index < 0 || index >= Count) { yield break; } 45 | foreach (uint value in Indices[index]) { yield return value; } 46 | } 47 | 48 | public override int Count 49 | { 50 | get { return Indices.Count; } 51 | } 52 | 53 | public IList> Indices 54 | { 55 | get; 56 | private set; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /HidSharp/Reports/IndexRange.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace HidSharp.Reports 21 | { 22 | public class IndexRange : Indexes 23 | { 24 | public IndexRange() 25 | { 26 | 27 | } 28 | 29 | public IndexRange(uint minimum, uint maximum) 30 | { 31 | Minimum = minimum; Maximum = maximum; 32 | } 33 | 34 | public override bool TryGetIndexFromValue(uint value, out int index) 35 | { 36 | if (value >= Minimum && value <= Maximum) 37 | { 38 | index = (int)(value - Minimum); return true; 39 | } 40 | 41 | return base.TryGetIndexFromValue(value, out index); 42 | } 43 | 44 | public override IEnumerable GetValuesFromIndex(int index) 45 | { 46 | if (index < 0 || index >= Count) { yield break; } 47 | yield return (uint)(Minimum + index); 48 | } 49 | 50 | public override int Count 51 | { 52 | get { return (int)(Maximum - Minimum + 1); } 53 | } 54 | 55 | public uint Minimum 56 | { 57 | get; 58 | set; 59 | } 60 | 61 | public uint Maximum 62 | { 63 | get; 64 | set; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /HidSharp/Reports/Indexes.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | 21 | namespace HidSharp.Reports 22 | { 23 | public class Indexes 24 | { 25 | static readonly Indexes _unset = new Indexes(); 26 | 27 | public bool ContainsValue(uint value) 28 | { 29 | int index; return TryGetIndexFromValue(value, out index); 30 | } 31 | 32 | public IEnumerable GetAllValues() 33 | { 34 | return Enumerable.Range(0, Count).SelectMany(index => GetValuesFromIndex(index)); 35 | } 36 | 37 | public virtual bool TryGetIndexFromValue(uint value, out int elementIndex) 38 | { 39 | elementIndex = -1; return false; 40 | } 41 | 42 | public virtual IEnumerable GetValuesFromIndex(int elementIndex) 43 | { 44 | yield break; 45 | } 46 | 47 | public virtual int Count 48 | { 49 | get { return 0; } 50 | } 51 | 52 | public static Indexes Unset 53 | { 54 | get { return _unset; } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /HidSharp/Reports/Report.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Collections.ObjectModel; 21 | using System.Diagnostics; 22 | using System.Linq; 23 | 24 | namespace HidSharp.Reports 25 | { 26 | public delegate void ReportScanCallback(byte[] buffer, int bitOffset, DataItem dataItem, int indexOfDataItem); 27 | public delegate void ReportValueCallback(DataValue dataValue); 28 | 29 | /// 30 | /// Reads and writes HID reports. 31 | /// 32 | public class Report 33 | { 34 | bool _computed; 35 | int _computedLength; 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | public Report() 41 | { 42 | DataItems = new ReportDataItems(this); 43 | } 44 | 45 | public IEnumerable GetAllUsages() 46 | { 47 | return DataItems.SelectMany(item => item.Usages.GetAllValues()); 48 | } 49 | 50 | /// 51 | /// Reads a HID report, calling back a provided function for each data item. 52 | /// 53 | /// The buffer containing the report. 54 | /// The offset to begin reading the report at. 55 | /// 56 | /// This callback will be called for each data item. 57 | /// Use this to read every value you need. 58 | /// 59 | public void Read(byte[] buffer, int offset, ReportScanCallback callback) 60 | { 61 | Throw.If.Null(buffer).OutOfRange(buffer, offset, Length).Null(callback); 62 | if (buffer[offset] != ReportID) { throw new ArgumentException("Report ID not correctly set.", "buffer"); } 63 | int bitOffset = (offset + 1) * 8; 64 | 65 | var dataItems = DataItems; 66 | int dataItemCount = dataItems.Count; 67 | for (int indexOfDataItem = 0; indexOfDataItem < dataItemCount; indexOfDataItem ++) 68 | { 69 | var dataItem = dataItems[indexOfDataItem]; 70 | callback(buffer, bitOffset, dataItem, indexOfDataItem); 71 | bitOffset += dataItem.TotalBits; 72 | } 73 | } 74 | 75 | public void Read(byte[] buffer, int offset, ReportValueCallback callback) 76 | { 77 | Read(buffer, offset, (readBuffer, bitOffset, dataItem, indexOfDataItem) => 78 | { 79 | int elementCount = dataItem.ElementCount; 80 | for (int elementIndex = 0; elementIndex < elementCount; elementIndex++) 81 | { 82 | DataValue value; 83 | if (dataItem.TryReadValue(readBuffer, bitOffset, elementIndex, out value)) 84 | { 85 | callback(value); 86 | } 87 | } 88 | }); 89 | } 90 | 91 | /// 92 | /// Writes a HID report, calling back a provided function for each data item. 93 | /// 94 | /// 95 | /// This callback will be called for each report data item. 96 | /// Write to each data item to write a complete HID report. 97 | /// 98 | public byte[] Write(ReportScanCallback callback) 99 | { 100 | byte[] buffer = new byte[Length]; 101 | Write(buffer, 0, callback); 102 | return buffer; 103 | } 104 | 105 | public void Write(byte[] buffer, int offset, ReportScanCallback callback) 106 | { 107 | Throw.If.OutOfRange(buffer, offset, Length); 108 | buffer[offset] = ReportID; Array.Clear(buffer, offset + 1, Length - 1); 109 | Read(buffer, offset, callback); 110 | } 111 | 112 | internal void InvalidateBitCount() 113 | { 114 | _computed = false; 115 | } 116 | 117 | void ComputeLength() 118 | { 119 | if (_computed) { return; } 120 | 121 | { 122 | int bits = 0; 123 | foreach (DataItem dataItem in DataItems) { bits += dataItem.TotalBits; } 124 | _computedLength = (bits + 7) / 8 + 1; 125 | } 126 | 127 | _computed = true; 128 | } 129 | 130 | public byte[] CreateBuffer() 131 | { 132 | byte[] buffer = new byte[Length]; 133 | buffer[0] = ReportID; 134 | return buffer; 135 | } 136 | 137 | public DeviceItem DeviceItem 138 | { 139 | get; 140 | internal set; 141 | } 142 | 143 | public IList DataItems 144 | { 145 | get; 146 | private set; 147 | } 148 | 149 | /// 150 | /// The length of this particular report. 151 | /// The Report ID is included in this length. 152 | /// 153 | public int Length 154 | { 155 | get { ComputeLength(); return _computedLength; } 156 | } 157 | 158 | /// 159 | /// The Report ID. 160 | /// 161 | public byte ReportID 162 | { 163 | get; 164 | set; 165 | } 166 | 167 | public ReportType ReportType 168 | { 169 | get; 170 | set; 171 | } 172 | 173 | #region ReportDataItems 174 | sealed class ReportDataItems : Collection 175 | { 176 | Report _report; 177 | 178 | public ReportDataItems(Report report) 179 | { 180 | Debug.Assert(report != null); 181 | _report = report; 182 | } 183 | 184 | protected override void ClearItems() 185 | { 186 | foreach (var item in this) { item.Report = null; } 187 | base.ClearItems(); 188 | _report.InvalidateBitCount(); 189 | } 190 | 191 | protected override void InsertItem(int index, DataItem item) 192 | { 193 | Throw.If.Null(item).False(item.Report == null); 194 | item.Report = _report; 195 | base.InsertItem(index, item); 196 | _report.InvalidateBitCount(); 197 | } 198 | 199 | protected override void RemoveItem(int index) 200 | { 201 | this[index].Report = null; 202 | base.RemoveItem(index); 203 | _report.InvalidateBitCount(); 204 | } 205 | 206 | protected override void SetItem(int index, DataItem item) 207 | { 208 | throw new NotImplementedException(); 209 | } 210 | } 211 | #endregion 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /HidSharp/Reports/ReportDescriptorParseState.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013, 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using HidSharp.Reports.Encodings; 21 | 22 | namespace HidSharp.Reports 23 | { 24 | // TODO: Make this public if anyone finds value in doing so. For now let's not lock ourselves in. 25 | sealed class ReportDescriptorParseState 26 | { 27 | public ReportDescriptorParseState() 28 | { 29 | RootItem = new DescriptorCollectionItem(); 30 | GlobalItemStateStack = new Stack>(); 31 | LocalItemState = new List>(); 32 | Reset(); 33 | } 34 | 35 | public void Reset() 36 | { 37 | CurrentCollectionItem = RootItem; 38 | RootItem.ChildItems.Clear(); 39 | RootItem.CollectionType = 0; 40 | 41 | GlobalItemStateStack.Clear(); 42 | GlobalItemStateStack.Push(new Dictionary()); 43 | LocalItemState.Clear(); 44 | } 45 | 46 | public EncodedItem GetGlobalItem(GlobalItemTag tag) 47 | { 48 | EncodedItem value; 49 | GlobalItemState.TryGetValue(tag, out value); 50 | return value; 51 | } 52 | 53 | public uint GetGlobalItemValue(GlobalItemTag tag) 54 | { 55 | EncodedItem item = GetGlobalItem(tag); 56 | return item != null ? item.DataValue : 0; 57 | } 58 | 59 | public bool IsGlobalItemSet(GlobalItemTag tag) 60 | { 61 | return GlobalItemState.ContainsKey(tag); 62 | } 63 | 64 | public DescriptorCollectionItem CurrentCollectionItem 65 | { 66 | get; 67 | set; 68 | } 69 | 70 | public DescriptorCollectionItem RootItem 71 | { 72 | get; 73 | private set; 74 | } 75 | 76 | public IDictionary GlobalItemState 77 | { 78 | get { return GlobalItemStateStack.Peek(); } 79 | } 80 | 81 | public Stack> GlobalItemStateStack 82 | { 83 | get; 84 | private set; 85 | } 86 | 87 | public IList> LocalItemState 88 | { 89 | get; 90 | private set; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /HidSharp/Reports/ReportType.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports 19 | { 20 | public enum ReportType 21 | { 22 | Input, 23 | Output, 24 | Feature 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/CurrentUnit.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible units of current. 22 | /// 23 | public enum CurrentUnit 24 | { 25 | /// 26 | /// The unit system has no unit of current. 27 | /// 28 | None, 29 | 30 | /// 31 | /// The unit of current is the Ampere. 32 | /// 33 | Ampere 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/LengthUnit.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible units of length. 22 | /// 23 | public enum LengthUnit 24 | { 25 | /// 26 | /// The unit system has no unit of length. 27 | /// 28 | None, 29 | 30 | /// 31 | /// The unit of length is the centimeter (occurs in the SI Linear unit system). 32 | /// 33 | Centimeter, 34 | 35 | /// 36 | /// The unit of length is the radian (occurs in the SI Rotation unit system). 37 | /// 38 | Radians, 39 | 40 | /// 41 | /// The unit of length is the inch (occurs in the English Linear unit system). 42 | /// 43 | Inch, 44 | 45 | /// 46 | /// The unit of length is the degree (occurs in the English Rotation unit system). 47 | /// 48 | Degrees 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/LuminousIntensityUnit.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible units of luminous intensity. 22 | /// 23 | public enum LuminousIntensityUnit 24 | { 25 | /// 26 | /// The unit system has no unit of luminous intensity. 27 | /// 28 | None, 29 | 30 | /// 31 | /// The unit of luminous intensity is the candela. 32 | /// 33 | Candela 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/MassUnit.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible units of mass. 22 | /// 23 | public enum MassUnit 24 | { 25 | /// 26 | /// The unit system has no unit of mass. 27 | /// 28 | None, 29 | 30 | /// 31 | /// The unit of mass is the gram (occurs in the SI Linear and Rotation unit systems). 32 | /// 33 | Gram, 34 | 35 | /// 36 | /// The unit of mass is the slug (occurs in the English Linear and Rotation unit systems). 37 | /// 38 | Slug 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/TemperatureUnit.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible units of temperature. 22 | /// 23 | public enum TemperatureUnit 24 | { 25 | /// 26 | /// The unit system has no unit of temperature. 27 | /// 28 | None, 29 | 30 | /// 31 | /// The unit of temperature is Kelvin (occurs in SI Linear and Rotation unit systems). 32 | /// 33 | Kelvin, 34 | 35 | /// 36 | /// The unit of temperature is Fahrenheit (occurs in English Linear and Rotation unit systems). 37 | /// 38 | Fahrenheit 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/TimeUnit.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible units of time. 22 | /// 23 | public enum TimeUnit 24 | { 25 | /// 26 | /// The unit system has no unit of time. 27 | /// 28 | None, 29 | 30 | /// 31 | /// The unit of time is seconds. 32 | /// 33 | Seconds 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/UnitKind.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2018 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | public enum UnitKind 21 | { 22 | Length = 1, 23 | Mass, 24 | Time, 25 | Temperature, 26 | Current, 27 | LuminousIntensity 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HidSharp/Reports/Units/UnitSystem.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2011, 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp.Reports.Units 19 | { 20 | /// 21 | /// Defines the possible unit systems. 22 | /// 23 | public enum UnitSystem 24 | { 25 | /// 26 | /// No units are used. 27 | /// 28 | None = 0, 29 | 30 | /// 31 | /// The SI Linear unit system uses centimeters for length, grams for mass, seconds for time, 32 | /// Kelvin for temperature, Amperes for current, and candelas for luminous intensity. 33 | /// 34 | SILinear, 35 | 36 | /// 37 | /// The SI Rotation unit system uses radians for length, grams for mass, seconds for time, 38 | /// Kelvin for temperature, Amperes for current, and candelas for luminous intensity. 39 | /// 40 | SIRotation, 41 | 42 | /// 43 | /// The English Linear unit system uses inches for length, slugs for mass, seconds for time, 44 | /// Fahrenheit for temperature, Amperes for current, and candelas for luminous intensity. 45 | /// 46 | EnglishLinear, 47 | 48 | /// 49 | /// The English Rotation unit system uses degrees for length, slugs for mass, seconds for time, 50 | /// Fahrenheit for temperature, Amperes for current, and candelas for luminous intensity. 51 | /// 52 | EnglishRotation 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /HidSharp/SerialDevice.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp 21 | { 22 | /// 23 | /// Represents a serial device. 24 | /// 25 | public abstract class SerialDevice : Device 26 | { 27 | /// 28 | public new SerialStream Open() 29 | { 30 | return Open(null); 31 | } 32 | 33 | /// 34 | public new SerialStream Open(OpenConfiguration openConfig) 35 | { 36 | return (SerialStream)base.Open(openConfig); 37 | } 38 | 39 | /// 40 | public bool TryOpen(out SerialStream stream) 41 | { 42 | return TryOpen(null, out stream); 43 | } 44 | 45 | /// 46 | public bool TryOpen(OpenConfiguration openConfig, out SerialStream stream) 47 | { 48 | DeviceStream baseStream; 49 | bool result = base.TryOpen(openConfig, out baseStream); 50 | stream = (SerialStream)baseStream; return result; 51 | } 52 | 53 | /// 54 | public override string GetFriendlyName() 55 | { 56 | return GetFileSystemName(); 57 | } 58 | 59 | public override bool HasImplementationDetail(Guid detail) 60 | { 61 | return base.HasImplementationDetail(detail) || detail == ImplementationDetail.SerialDevice; 62 | } 63 | 64 | /// 65 | public override string ToString() 66 | { 67 | string fileSystemName = "(unknown filesystem name)"; 68 | try { fileSystemName = GetFileSystemName(); } catch { } 69 | 70 | return string.Format("{0} ({1})", fileSystemName, DevicePath); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /HidSharp/SerialParity.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | namespace HidSharp 19 | { 20 | public enum SerialParity 21 | { 22 | None = 0, 23 | Odd = 1, 24 | Even = 2 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /HidSharp/SerialSettings.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp 21 | { 22 | struct SerialSettings 23 | { 24 | public static readonly SerialSettings Default = new SerialSettings() 25 | { 26 | BaudRate = 9600, DataBits = 8, Parity = SerialParity.None, StopBits = 1 27 | }; 28 | 29 | public int BaudRate; 30 | public int DataBits; 31 | public SerialParity Parity; 32 | public int StopBits; 33 | 34 | public void SetBaudRate(int baudRate, object @lock, ref bool settingsChanged) 35 | { 36 | if (baudRate < 0) { throw new NotSupportedException(); } 37 | 38 | lock (@lock) 39 | { 40 | if (BaudRate == baudRate) { return; } 41 | //Console.WriteLine(string.Format("Baud {0} -> {1}", BaudRate, baudRate)); 42 | BaudRate = baudRate; settingsChanged = true; 43 | } 44 | } 45 | 46 | public void SetDataBits(int dataBits, object @lock, ref bool settingsChanged) 47 | { 48 | if (dataBits < 7 || dataBits > 8) { throw new NotSupportedException(); } 49 | 50 | lock (@lock) 51 | { 52 | if (DataBits == dataBits) { return; } 53 | //Console.WriteLine(string.Format("Data Bits {0} -> {1}", DataBits, dataBits)); 54 | DataBits = dataBits; settingsChanged = true; 55 | } 56 | } 57 | 58 | public void SetParity(SerialParity parity, object @lock, ref bool settingsChanged) 59 | { 60 | lock (@lock) 61 | { 62 | if (Parity == parity) { return; } 63 | //Console.WriteLine(string.Format("Parity {0} -> {1}", Parity, parity)); 64 | Parity = parity; settingsChanged = true; 65 | } 66 | } 67 | 68 | public void SetStopBits(int stopBits, object @lock, ref bool settingsChanged) 69 | { 70 | if (stopBits < 1 || stopBits > 2) { throw new NotSupportedException(); } 71 | 72 | lock (@lock) 73 | { 74 | if (StopBits == stopBits) { return; } 75 | //Console.WriteLine(string.Format("Stop Bits {0} -> {1}", StopBits, stopBits)); 76 | StopBits = stopBits; settingsChanged = true; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /HidSharp/SerialStream.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System.Collections.Generic; 19 | using System.Reflection; 20 | using System.Text; 21 | 22 | namespace HidSharp 23 | { 24 | /// 25 | /// Communicates with a serial device. 26 | /// 27 | public abstract class SerialStream : DeviceStream 28 | { 29 | string _newLine; 30 | 31 | /// 32 | protected SerialStream(SerialDevice device) 33 | : base(device) 34 | { 35 | ReadTimeout = 3000; 36 | WriteTimeout = 3000; 37 | 38 | NewLine = "\r\n"; 39 | BaudRate = SerialSettings.Default.BaudRate; 40 | DataBits = SerialSettings.Default.DataBits; 41 | Parity = SerialSettings.Default.Parity; 42 | StopBits = SerialSettings.Default.StopBits; 43 | } 44 | 45 | public string ReadTo(string ending) 46 | { 47 | Throw.If.NullOrEmpty(ending, "ending"); 48 | 49 | var bytes = new List(); 50 | var endingBytes = Encoding.GetBytes(ending); 51 | int matchBytes = 0; 52 | 53 | while (true) 54 | { 55 | int @byte = ReadByte(); 56 | if (@byte < 0) { break; } 57 | bytes.Add((byte)@byte); 58 | 59 | if (@byte == endingBytes[matchBytes]) 60 | { 61 | if (++matchBytes == endingBytes.Length) 62 | { 63 | break; 64 | } 65 | } 66 | else 67 | { 68 | matchBytes = 0; 69 | } 70 | } 71 | 72 | @bytes.RemoveRange(bytes.Count - matchBytes, matchBytes); 73 | return Encoding.GetString(@bytes.ToArray()); 74 | } 75 | 76 | [Obfuscation(Exclude = true)] 77 | public string ReadLine() 78 | { 79 | return ReadTo(NewLine); 80 | } 81 | 82 | [Obfuscation(Exclude = true)] 83 | public void Write(string s) 84 | { 85 | Throw.If.Null(s, "s"); 86 | byte[] bytes = Encoding.GetBytes(s); 87 | Write(bytes, 0, bytes.Length); 88 | } 89 | 90 | [Obfuscation(Exclude = true)] 91 | public void WriteLine(string s) 92 | { 93 | Throw.If.Null(s, "s"); 94 | Write(s + NewLine); 95 | } 96 | 97 | public abstract int BaudRate 98 | { 99 | get; 100 | set; 101 | } 102 | 103 | public abstract int DataBits 104 | { 105 | get; 106 | set; 107 | } 108 | 109 | public abstract SerialParity Parity 110 | { 111 | get; 112 | set; 113 | } 114 | 115 | public abstract int StopBits 116 | { 117 | get; 118 | set; 119 | } 120 | 121 | Encoding Encoding 122 | { 123 | get { return Encoding.UTF8; } 124 | } 125 | 126 | public string NewLine 127 | { 128 | get { return _newLine; } 129 | set 130 | { 131 | Throw.If.NullOrEmpty(value, "NewLine"); 132 | _newLine = value; 133 | } 134 | } 135 | 136 | /// 137 | /// Gets the associated with this stream. 138 | /// 139 | public new SerialDevice Device 140 | { 141 | get { return (SerialDevice)base.Device; } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /HidSharp/Throw.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2013 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | 21 | namespace HidSharp 22 | { 23 | sealed class Throw 24 | { 25 | Throw() 26 | { 27 | 28 | } 29 | 30 | public static Throw If 31 | { 32 | get { return null; } 33 | } 34 | } 35 | 36 | static class ThrowExtensions 37 | { 38 | public static Throw False(this Throw self, bool condition) 39 | { 40 | if (!condition) { throw new ArgumentException(); } 41 | return null; 42 | } 43 | 44 | public static Throw False(this Throw self, bool condition, string message, string paramName) 45 | { 46 | if (!condition) { throw new ArgumentException(message, paramName); } 47 | return null; 48 | } 49 | 50 | public static Throw Negative(this Throw self, int value, string paramName) 51 | { 52 | if (value < 0) { throw new ArgumentOutOfRangeException(paramName); } 53 | return null; 54 | } 55 | 56 | public static Throw Null(this Throw self, T value) 57 | { 58 | if (value == null) { throw new ArgumentNullException(); } 59 | return null; 60 | } 61 | 62 | public static Throw Null(this Throw self, T value, string paramName) 63 | { 64 | if (value == null) { throw new ArgumentNullException(paramName); } 65 | return null; 66 | } 67 | 68 | public static Throw NullOrEmpty(this Throw self, string value, string paramName) 69 | { 70 | Throw.If.Null(value, paramName); 71 | if (value.Length == 0) { throw new ArgumentException("Must not be empty.", paramName); } 72 | return null; 73 | } 74 | 75 | public static Throw OutOfRange(this Throw self, int bufferSize, int offset, int count) 76 | { 77 | if (offset < 0 || offset > bufferSize) { throw new ArgumentOutOfRangeException("offset"); } 78 | if (count < 0 || count > bufferSize - offset) { throw new ArgumentOutOfRangeException("count"); } 79 | return null; 80 | } 81 | 82 | public static Throw OutOfRange(this Throw self, IList buffer, int offset, int count) 83 | { 84 | Throw.If.Null(buffer, "buffer").OutOfRange(buffer.Count, offset, count); 85 | return null; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /HidSharp/Utility/BcdHelper.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | 20 | namespace HidSharp.Utility 21 | { 22 | /// 23 | /// Converts USB device release numbers to and from binary-coded decimal. 24 | /// 25 | static class BcdHelper 26 | { 27 | /// 28 | /// Converts a USB device release number to binary-coded decimal. 29 | /// 30 | /// The device release number. 31 | /// The device release number, in binary-coded decimal. 32 | public static int FromVersion(Version version) 33 | { 34 | Throw.If.Null(version); 35 | return (version.Major / 10) << 12 | (version.Major % 10) << 8 | (version.Minor / 10) << 4 | (version.Minor % 10); 36 | } 37 | 38 | /// 39 | /// Converts a USB device release number from binary-coded decimal. 40 | /// 41 | /// The device release number, in binary-coded decimal. 42 | /// The device release number. 43 | public static Version ToVersion(int bcd) 44 | { 45 | Throw.If.False(bcd >= ushort.MinValue && bcd <= ushort.MaxValue); 46 | return new Version(((bcd >> 12) & 0xf) * 10 + ((bcd >> 8) & 0xf), ((bcd >> 4) & 0xf) * 10 + (bcd & 0xf)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /HidSharp/Utility/HResult.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2017 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Reflection; 20 | using System.Runtime.InteropServices; 21 | 22 | namespace HidSharp.Utility 23 | { 24 | [Obsolete("This class is experimental and its functionality may be moved elsewhere in the future. Please do not rely on it.")] 25 | public static class HResult 26 | { 27 | public const int FileNotFound = unchecked((int)0x80070002); // ERROR_FILE_NOT_FOUND 28 | public const int SharingViolation = unchecked((int)0x80070020); // ERROR_SHARING_VIOLATION 29 | public const int SemTimeout = unchecked((int)0x80070079); // ERROR_SEM_TIMEOUT 30 | 31 | public static int FromException(Exception exception) 32 | { 33 | Throw.If.Null(exception); 34 | 35 | try 36 | { 37 | // This works with .NET 4.0 as well as later versions. Also, it does not change any state. 38 | return (int)exception.GetType().InvokeMember("HResult", 39 | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, 40 | null, exception, new object[0]); 41 | } 42 | catch 43 | { 44 | return Marshal.GetHRForException(exception); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /HidSharp/Utility/HidSharpDiagnostics.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* Copyright 2019 James F. Bellinger 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. */ 16 | #endregion 17 | 18 | using System; 19 | using System.Diagnostics; 20 | 21 | namespace HidSharp.Utility 22 | { 23 | public static class HidSharpDiagnostics 24 | { 25 | static HidSharpDiagnostics() 26 | { 27 | PerformStrictChecks = false; 28 | } 29 | 30 | internal static void PerformStrictCheck(bool condition, string message) 31 | { 32 | if (!condition) 33 | { 34 | message += "\n\nTo disable this exception, set HidSharpDiagnostics.PerformStrictChecks to false."; 35 | throw new InvalidOperationException(message); 36 | } 37 | } 38 | 39 | internal static void Trace(string message) 40 | { 41 | if (!EnableTracing) { return; } 42 | System.Diagnostics.Trace.WriteLine(message, "HIDSharp"); 43 | } 44 | 45 | internal static void Trace(string formattedMessage, object arg) 46 | { 47 | if (!EnableTracing) { return; } 48 | Trace(string.Format(formattedMessage, arg)); 49 | } 50 | 51 | internal static void Trace(string formattedMessage, params object[] args) 52 | { 53 | if (!EnableTracing) { return; } 54 | Trace(string.Format(formattedMessage, args)); 55 | } 56 | 57 | public static bool EnableTracing 58 | { 59 | get; 60 | set; 61 | } 62 | 63 | public static bool PerformStrictChecks 64 | { 65 | get; 66 | set; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | HIDSharp 2 | Copyright 2010-2019 James F. Bellinger 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HIDSharp 2 | 3 | HIDSharp is a multiplatform C# library for USB HID devices. 4 | 5 | Version 2.0 allows you to read and parse reports from any USB HID input device. You can read USB gamepads, scales, anything you need. It does this by providing full report descriptor and report parsing capability. HIDSharp is, to my knowledge, the first driverless cross-platform library which can do this! Of course, raw reading and writing is still fully supported. 6 | 7 | Version 1.5 and below are COM enabled to allow use by VB6 and MS Access programs (the .NET Framework will of course need to be installed). If there is demand I may add COM support to HIDSharp 2.0. 8 | 9 | HIDSharp has received eight years of continual use with a Dymo Scale in MS Access, and seven years in commercial software with a wide variety of USB HID devices I've developed, so I know it to be reliable. 10 | 11 | HIDSharp supports Windows, MacOS, and Linux (hidraw). 12 | 13 | HIDSharp uses the Apache open-source license. 14 | 15 | Originally distributed by James F. Bellinger through [his webpage][Origin]. Available as a [Nuget package][OnNuget]. 16 | 17 | [Origin]: https://www.zer7.com/software/hidsharp 18 | [OnNuget]: https://www.nuget.org/packages/HidSharp/ 19 | --------------------------------------------------------------------------------