I code a C# Console application ,try get my headphone battery info
class BluetoothAPIs
class BluetoothAPIs
{
//https://docs.microsoft.com/zh-cn/windows/win32/api/bluetoothleapis/nf-bluetoothleapis-bluetoothgattgetservices
[DllImport("BluetoothAPIs.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int BluetoothGATTGetServices(
IntPtr hDevice,
UInt16 ServicesBufferCount,
IntPtr ServicesBuffer,
ref UInt16 ServicesBufferActual,
UInt32 Flags
);
//https://docs.microsoft.com/zh-cn/windows/win32/api/bthledef/ns-bthledef-bth_le_uuid
[StructLayout(LayoutKind.Sequential)]
public struct BTH_LE_UUID
{
public Boolean isShortUuid;
public UInt16 ShortUuid;
public Guid LongUuid;
}
//https://docs.microsoft.com/zh-cn/windows/win32/api/bthledef/ns-bthledef-bth_le_gatt_service
[StructLayout(LayoutKind.Sequential)]
public struct BTH_LE_GATT_SERVICE
{
public BTH_LE_UUID ServiceUuid;
public UInt16 AttributeHandle;
}
//https://docs.microsoft.com/en-us/windows/win32/api/bluetoothleapis/nf-bluetoothleapis-bluetoothgattgetcharacteristics
[DllImport("BluetoothAPIs.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int BluetoothGATTGetCharacteristics(
IntPtr hDevice,
ref BTH_LE_GATT_SERVICE Service,
UInt16 CharacteristicsBufferCount,
IntPtr CharacteristicsBuffer,
ref UInt16 CharacteristicsBufferActual,
UInt32 Flags
);
//https://docs.microsoft.com/en-us/windows/win32/api/bthledef/ns-bthledef-bth_le_gatt_characteristic
[StructLayout(LayoutKind.Sequential)]
public struct BTH_LE_GATT_CHARACTERISTIC
{
public UInt16 ServiceHandle;
public BTH_LE_UUID CharacteristicUuid;
public UInt16 AttributeHandle;
public UInt16 CharacteristicValueHandle;
public Boolean IsBroadcastable;
public Boolean IsReadable;
public Boolean IsWritable;
public Boolean IsWritableWithoutResponse;
public Boolean IsSignedWritable;
public Boolean IsNotifiable;
public Boolean IsIndicatable;
public Boolean HasExtendedProperties;
}
//https://docs.microsoft.com/en-us/windows/win32/api/bluetoothleapis/nf-bluetoothleapis-bluetoothgattgetcharacteristicvalue
[DllImport("BluetoothAPIs.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int BluetoothGATTGetCharacteristicValue(
IntPtr hDevice,
ref BTH_LE_GATT_CHARACTERISTIC Characteristic,
UInt32 CharacteristicValueDataSize,
ref BTH_LE_GATT_CHARACTERISTIC_VALUE CharacteristicValue,
out UInt16 CharacteristicValueSizeRequired,
UInt32 Flags
);
//https://docs.microsoft.com/en-us/windows/win32/api/bthledef/ns-bthledef-bth_le_gatt_characteristic_value
[StructLayout(LayoutKind.Sequential)]
public struct BTH_LE_GATT_CHARACTERISTIC_VALUE
{
public UInt32 DataSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte[] Data;
}
public static readonly UInt32 BLUETOOTH_GATT_FLAG_NONE = 0;
public static readonly UInt32 BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE = 0x00000004;
}
I try this:
IntPtr characteristicsBufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC)) * characteristicsBufferCount);
UInt16 characteristicsBufferActual = 0;
BluetoothAPIs.BluetoothGATTGetCharacteristics(hDevice, ref service, characteristicsBufferCount, characteristicsBufferPtr, ref characteristicsBufferActual, BluetoothAPIs.BLUETOOTH_GATT_FLAG_NONE);
for (int n = 0; n < characteristicsBufferActual; n++)
{
BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC characteristic = Marshal.PtrToStructure<BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC>(characteristicsBufferPtr + n * Marshal.SizeOf(typeof(BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC)));
BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC_VALUE characteristicValue = new BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC_VALUE();
UInt16 characteristicValueSizeRequired = 0;
BluetoothAPIs.BluetoothGATTGetCharacteristicValue(hDevice, ref characteristic, 256, ref characteristicValue, out characteristicValueSizeRequired, BluetoothAPIs.BLUETOOTH_GATT_FLAG_NONE);
if (characteristic.CharacteristicUuid.ShortUuid == 0x2A19) // battery level
{
Console.WriteLine("Battery Level: {0}", characteristicValue.Data[0]);
}
else if (characteristic.CharacteristicUuid.ShortUuid == 0x2A01) // appearance
{
int appearance = BitConverter.ToInt32(characteristicValue.Data);
string appearanceName = appearanceDict.GetValueOrDefault(appearance, "Unknown");
Console.WriteLine("Appearance: {1}, Data: {2}", appearance, appearanceName);
}
else //string
{
Console.WriteLine("UUID: {0}, DataSize: {1}, Data: {2}", characteristic.CharacteristicUuid.ShortUuid, characteristicValue.DataSize, Encoding.ASCII.GetString(characteristicValue.Data, 0, (int)characteristicValue.DataSize));
}
}
When n = 0, I can get a struct 'BTH_LE_GATT_CHARACTERISTIC'. But n > 0, get struct fail from ptr. How to get next '' struct or get struct array
There are full code: https://gist.github.com/cd2b1a504ee9155e8dcb2cc7c62257d7.git
The result of Marshal.SizeOf(typeof(BluetoothAPIs.BTH_LE_GATT_CHARACTERISTIC))
is 60
. However, in C++, sizeof(BTH_LE_GATT_CHARACTERISTIC)
is 36
.
The issues is:
Boolean
in C# is 4 bytes while BOOLEAN
in C++ is one byte.
So in C#, the corresponding definitions of BTH_LE_UUID
and BTH_LE_GATT_CHARACTERISTIC
will like this:
[StructLayout(LayoutKind.Sequential)]
public struct BTH_LE_UUID
{
public Byte isShortUuid;
public UInt16 ShortUuid;
public Guid LongUuid;
}
[StructLayout(LayoutKind.Sequential)]
public struct BTH_LE_GATT_CHARACTERISTIC
{
public UInt16 ServiceHandle;
public BTH_LE_UUID CharacteristicUuid;
public UInt16 AttributeHandle;
public UInt16 CharacteristicValueHandle;
public Byte IsBroadcastable;
public Byte IsReadable;
public Byte IsWritable;
public Byte IsWritableWithoutResponse;
public Byte IsSignedWritable;
public Byte IsNotifiable;
public Byte IsIndicatable;
public Byte HasExtendedProperties;
}
User contributions licensed under CC BY-SA 3.0