如何在C#中获取LMP版本号?兼容C/C++实现方案
问题描述
我可以接受C/C实现方案,自行完成跨语言适配。目前已能在C中获取LMP Subversion(值为8207),但不知如何获取LMP版本(值为11)。需要通过编程方式获取该值,以此判断设备是否支持特定功能(如4.0及以上版本支持BLE)。我已花费大量时间搜索,仅能通过设备面板手动查看LMP值,未找到编程获取的相关资料。
基于@Mike Petrichenko评论与@Iłya Bursov回答的C#实现
列出支持功能的简易代码
namespace BluetoothInfoReader { internal class Program { static void Main(string[] args) { var features = Api.GetSupportedFeatures(); foreach(HostFeature feature in Enum.GetValues(typeof(HostFeature))) { if (feature != HostFeature.None) { Console.WriteLine($"{feature}: {((features & feature) == feature)}"); } } var info = Api.GetRadioInfo(); // Any more info required can be gotten from "info" Console.ReadLine(); } } }
配套结构体与枚举
namespace Bluetooth { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct FindRadioParams { public FindRadioParams() { dwSize = (uint)Marshal.SizeOf(); } public uint dwSize; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct DeviceInfo { public uint flags; public ulong address; public uint classOfDevice; // 248 is the value of BTH_MAX_NAME_SIZE [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 248)] public string name; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct RadioInfo { public ulong lmpSupportedFeatures; public ushort mfg; public ushort lmpSubversion; public byte lmpVersion; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct LocalRadioInfo { public DeviceInfo localInfo; public uint flags; public ushort hciRevision; public byte hciVersion; public RadioInfo radioInfo; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Overlapped { public ulong Internal; public ulong InternalHigh; public IntPtr Pointer; public IntPtr hEvent; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct HostFeatureMask { public HostFeature Mask; public ulong Reserved1; public ulong Reserved2; } public enum HostFeature : ulong { None = 0, EnhancedRetransmissionMode = (0x0000000000000001), StreamingMode = (0x0000000000000002), LowEnergy = (0x0000000000000004), ScoHci = (0x0000000000000008), ScoHciBypass = (0x0000000000000010) } public static class IoControl { const int FILE_DEVICE_BLUETOOTH = 0x00000041; const int METHOD_BUFFERED = 0; const int FILE_ANY_ACCESS = 0; const int BTH_IOCTL_BASE = 0; private static uint CtlCodeCreator(ushort deviceType, ushort function, byte method, byte access) { uint result = (uint)((deviceType << 16) | (access << 14) | (function << 2) | method); return result; } private static uint BthCtlCodeCreator(ushort id) { return CtlCodeCreator((ushort)FILE_DEVICE_BLUETOOTH, id, (byte)METHOD_BUFFERED, (byte)FILE_ANY_ACCESS); } public static readonly uint GetLocalInfo = BthCtlCodeCreator(BTH_IOCTL_BASE + 0x00); public static readonly uint GetHostSupportedFeatures = BthCtlCodeCreator(BTH_IOCTL_BASE + 0x88); } public static class Api { [DllImport("bthprops.cpl")] public static extern IntPtr BluetoothFindFirstRadio([In] ref FindRadioParams findRadioParams, [Out] out IntPtr hRadio); [DllImport("bthprops.cpl")] public static extern bool BluetoothFindNextRadio([In] IntPtr hFindHandle, [Out] out IntPtr hRadio); [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32.dll")] public static extern bool DeviceIoControl([In] IntPtr hDevice, uint dwIoControlCode, [In] IntPtr inBuffer, uint nInBufferSize, [Out] IntPtr outBuffer, uint nOutBufferSize, [Out] out uint bytesReturned, [In, Out] ref Bluetooth.Overlapped overlapped); public static bool DeviceIoControl<T>([In] IntPtr hDevice, uint dwIoControlCode, [In] IntPtr inBuffer, uint nInBufferSize, [Out] out T outBuffer) where T : struct { int size = Marshal.SizeOf<T>(); IntPtr buffer = Marshal.AllocHGlobal(size); Overlapped overlapped = new Overlapped(); var result = DeviceIoControl(hDevice, dwIoControlCode, inBuffer, nInBufferSize, buffer, (uint)size, out uint bytesReturned, ref overlapped); if (bytesReturned != size) { // Houston we have a problem. } outBuffer = Marshal.PtrToStructure<T>(buffer); return result; } public static HostFeature GetSupportedFeatures() { HostFeature result = HostFeature.None; FindRadioParams findParams = new FindRadioParams(); var findHandle = BluetoothFindFirstRadio(ref findParams, out IntPtr radioHandle); if (findHandle != IntPtr.Zero) { do { if (DeviceIoControl(radioHandle, IoControl.GetHostSupportedFeatures, IntPtr.Zero, 0, out Bluetooth.HostFeatureMask features)) { result = features.Mask; break; } } while (BluetoothFindNextRadio(findHandle, out radioHandle)); CloseHandle(radioHandle); } return result; } public static LocalRadioInfo GetRadioInfo() { LocalRadioInfo result = new LocalRadioInfo(); FindRadioParams findParams = new FindRadioParams(); var findHandle = BluetoothFindFirstRadio(ref findParams, out IntPtr radioHandle); if (findHandle != IntPtr.Zero) { do { if (DeviceIoControl(radioHandle, IoControl.GetLocalInfo, IntPtr.Zero, 0, out result)) { break; } } while (BluetoothFindNextRadio(findHandle, out radioHandle)); CloseHandle(radioHandle); } return result; } } }
内容的提问来源于stack exchange,提问作者K.Lawrence
相关产品推荐
相关产品推荐

