Index: device/bluetooth/bluetooth_low_energy_win.cc |
diff --git a/device/bluetooth/bluetooth_low_energy_win.cc b/device/bluetooth/bluetooth_low_energy_win.cc |
index 6e1cb81e46172e484bb187a1ee5198bdebcac3ee..24d940726e1a6806ffa1aa4562530dec7dad7ad3 100644 |
--- a/device/bluetooth/bluetooth_low_energy_win.cc |
+++ b/device/bluetooth/bluetooth_low_energy_win.cc |
@@ -62,14 +62,9 @@ bool StringToBluetoothAddress(const std::string& value, |
} |
int buffer[6]; |
- int result = sscanf_s(value.c_str(), |
- "%02X%02X%02X%02X%02X%02X", |
- &buffer[5], |
- &buffer[4], |
- &buffer[3], |
- &buffer[2], |
- &buffer[1], |
- &buffer[0]); |
+ int result = |
+ sscanf_s(value.c_str(), "%02X%02X%02X%02X%02X%02X", &buffer[5], |
+ &buffer[4], &buffer[3], &buffer[2], &buffer[1], &buffer[0]); |
if (result != 6) { |
*error = kInvalidBluetoothAddress; |
return false; |
@@ -172,36 +167,26 @@ bool CollectBluetoothLowEnergyDeviceProperty( |
std::string* error) { |
DWORD required_length; |
DEVPROPTYPE prop_type; |
- BOOL success = SetupDiGetDeviceProperty(device_info_handle.Get(), |
- device_info_data, |
- &key, |
- &prop_type, |
- NULL, |
- 0, |
- &required_length, |
- 0); |
+ BOOL success = |
+ SetupDiGetDeviceProperty(device_info_handle.Get(), device_info_data, &key, |
+ &prop_type, NULL, 0, &required_length, 0); |
if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) |
return false; |
scoped_ptr<uint8_t[]> prop_value(new uint8_t[required_length]); |
DWORD actual_length = required_length; |
- success = SetupDiGetDeviceProperty(device_info_handle.Get(), |
- device_info_data, |
- &key, |
- &prop_type, |
- prop_value.get(), |
- actual_length, |
- &required_length, |
- 0); |
+ success = SetupDiGetDeviceProperty(device_info_handle.Get(), device_info_data, |
+ &key, &prop_type, prop_value.get(), |
+ actual_length, &required_length, 0); |
if (!CheckSuccess(!!success, kDeviceInfoError, error)) |
return false; |
- if (!CheckExpectedLength( |
- actual_length, required_length, kDeviceInfoError, error)) { |
+ if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError, |
+ error)) { |
return false; |
} |
(*value) = scoped_ptr<DevicePropertyValue>( |
- new DevicePropertyValue(prop_type, prop_value.Pass(), actual_length)); |
+ new DevicePropertyValue(prop_type, std::move(prop_value), actual_length)); |
return true; |
} |
@@ -212,35 +197,28 @@ bool CollectBluetoothLowEnergyDeviceRegistryProperty( |
scoped_ptr<DeviceRegistryPropertyValue>* value, |
std::string* error) { |
ULONG required_length = 0; |
- BOOL success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(), |
- device_info_data, |
- property_id, |
- NULL, |
- NULL, |
- 0, |
- &required_length); |
+ BOOL success = SetupDiGetDeviceRegistryProperty( |
+ device_info_handle.Get(), device_info_data, property_id, NULL, NULL, 0, |
+ &required_length); |
if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) |
return false; |
scoped_ptr<uint8_t[]> property_value(new uint8_t[required_length]); |
ULONG actual_length = required_length; |
DWORD property_type; |
- success = SetupDiGetDeviceRegistryProperty(device_info_handle.Get(), |
- device_info_data, |
- property_id, |
- &property_type, |
- property_value.get(), |
- actual_length, |
- &required_length); |
+ success = SetupDiGetDeviceRegistryProperty( |
+ device_info_handle.Get(), device_info_data, property_id, &property_type, |
+ property_value.get(), actual_length, &required_length); |
if (!CheckSuccess(!!success, kDeviceInfoError, error)) |
return false; |
- if (!CheckExpectedLength( |
- actual_length, required_length, kDeviceInfoError, error)) { |
+ if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError, |
+ error)) { |
return false; |
} |
(*value) = DeviceRegistryPropertyValue::Create( |
- property_type, property_value.Pass(), actual_length).Pass(); |
+ property_type, std::move(property_value), actual_length) |
+ .Pass(); |
return true; |
} |
@@ -258,14 +236,12 @@ bool CollectBluetoothLowEnergyDeviceInstanceId( |
scoped_ptr<WCHAR[]> instance_id(new WCHAR[required_length]); |
ULONG actual_length = required_length; |
success = SetupDiGetDeviceInstanceId(device_info_handle.Get(), |
- device_info_data, |
- instance_id.get(), |
- actual_length, |
- &required_length); |
+ device_info_data, instance_id.get(), |
+ actual_length, &required_length); |
if (!CheckSuccess(!!success, kDeviceInfoError, error)) |
return false; |
- if (!CheckExpectedLength( |
- actual_length, required_length, kDeviceInfoError, error)) { |
+ if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError, |
+ error)) { |
return false; |
} |
@@ -283,11 +259,9 @@ bool CollectBluetoothLowEnergyDeviceFriendlyName( |
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info, |
std::string* error) { |
scoped_ptr<DeviceRegistryPropertyValue> property_value; |
- if (!CollectBluetoothLowEnergyDeviceRegistryProperty(device_info_handle, |
- device_info_data, |
- SPDRP_FRIENDLYNAME, |
- &property_value, |
- error)) { |
+ if (!CollectBluetoothLowEnergyDeviceRegistryProperty( |
+ device_info_handle, device_info_data, SPDRP_FRIENDLYNAME, |
+ &property_value, error)) { |
return false; |
} |
@@ -342,11 +316,9 @@ bool CollectBluetoothLowEnergyDeviceStatus( |
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info, |
std::string* error) { |
scoped_ptr<DevicePropertyValue> value; |
- if (!CollectBluetoothLowEnergyDeviceProperty(device_info_handle, |
- device_info_data, |
- DEVPKEY_Device_DevNodeStatus, |
- &value, |
- error)) { |
+ if (!CollectBluetoothLowEnergyDeviceProperty( |
+ device_info_handle, device_info_data, DEVPKEY_Device_DevNodeStatus, |
+ &value, error)) { |
return false; |
} |
@@ -374,40 +346,21 @@ bool CollectBluetoothLowEnergyDeviceServices( |
return false; |
} |
- USHORT required_length; |
- HRESULT hr = BluetoothGATTGetServices(file.GetPlatformFile(), |
- 0, |
- NULL, |
- &required_length, |
- BLUETOOTH_GATT_FLAG_NONE); |
- if (CheckNoData(hr, required_length)) |
- return true; |
- if (!CheckMoreData(hr, kDeviceInfoError, error)) |
- return false; |
- |
- scoped_ptr<BTH_LE_GATT_SERVICE[]> gatt_services( |
- new BTH_LE_GATT_SERVICE[required_length]); |
- USHORT actual_length = required_length; |
- hr = BluetoothGATTGetServices(file.GetPlatformFile(), |
- actual_length, |
- gatt_services.get(), |
- &required_length, |
- BLUETOOTH_GATT_FLAG_NONE); |
+ BTH_LE_GATT_SERVICE* primary_services; |
+ USHORT counts; |
+ HRESULT hr = device::win::ReadPrimaryServicesOfADevice( |
+ file.GetPlatformFile(), &primary_services, &counts); |
if (!CheckHResult(hr, kDeviceInfoError, error)) |
return false; |
- if (!CheckExpectedLength( |
- actual_length, required_length, kDeviceInfoError, error)) { |
- return false; |
- } |
- for (USHORT i = 0; i < actual_length; ++i) { |
- BTH_LE_GATT_SERVICE& gatt_service(gatt_services.get()[i]); |
+ for (USHORT i = 0; i < counts; ++i) { |
BluetoothLowEnergyServiceInfo* service_info = |
new BluetoothLowEnergyServiceInfo(); |
- service_info->uuid = gatt_service.ServiceUuid; |
+ service_info->uuid = primary_services[i].ServiceUuid; |
+ service_info->attribute_handle = primary_services[i].AttributeHandle; |
services->push_back(service_info); |
} |
- |
+ delete primary_services; |
return true; |
} |
@@ -419,11 +372,8 @@ bool CollectBluetoothLowEnergyDeviceInfo( |
// Retrieve required # of bytes for interface details |
ULONG required_length = 0; |
BOOL success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(), |
- device_interface_data, |
- NULL, |
- 0, |
- &required_length, |
- NULL); |
+ device_interface_data, NULL, 0, |
+ &required_length, NULL); |
if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error)) |
return false; |
@@ -439,16 +389,14 @@ bool CollectBluetoothLowEnergyDeviceInfo( |
device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); |
ULONG actual_length = required_length; |
- success = SetupDiGetDeviceInterfaceDetail(device_info_handle.Get(), |
- device_interface_data, |
- device_interface_detail_data, |
- actual_length, |
- &required_length, |
- &device_info_data); |
+ success = SetupDiGetDeviceInterfaceDetail( |
+ device_info_handle.Get(), device_interface_data, |
+ device_interface_detail_data, actual_length, &required_length, |
+ &device_info_data); |
if (!CheckSuccess(!!success, kDeviceInfoError, error)) |
return false; |
- if (!CheckExpectedLength( |
- actual_length, required_length, kDeviceInfoError, error)) { |
+ if (!CheckExpectedLength(actual_length, required_length, kDeviceInfoError, |
+ error)) { |
return false; |
} |
@@ -462,7 +410,8 @@ bool CollectBluetoothLowEnergyDeviceInfo( |
} |
if (!CollectBluetoothLowEnergyDeviceFriendlyName( |
device_info_handle, &device_info_data, result, error)) { |
- return false; |
+ if (device_info_data.ClassGuid == GUID_BLUETOOTHLE_DEVICE_INTERFACE) |
+ return false; |
} |
if (!CollectBluetoothLowEnergyDeviceAddress( |
device_info_handle, &device_info_data, result, error)) { |
@@ -479,19 +428,17 @@ bool CollectBluetoothLowEnergyDeviceInfo( |
enum DeviceInfoResult { kOk, kError, kNoMoreDevices }; |
DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice( |
+ GUID guid, |
const ScopedDeviceInfoSetHandle& device_info_handle, |
DWORD device_index, |
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info, |
std::string* error) { |
- // Enumerate device of BLUETOOTHLE_DEVICE interface class |
- GUID BluetoothInterfaceGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE; |
+ GUID BluetoothInterfaceGUID = guid; |
SP_DEVICE_INTERFACE_DATA device_interface_data = {0}; |
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); |
- BOOL success = ::SetupDiEnumDeviceInterfaces(device_info_handle.Get(), |
- NULL, |
- &BluetoothInterfaceGUID, |
- device_index, |
- &device_interface_data); |
+ BOOL success = ::SetupDiEnumDeviceInterfaces( |
+ device_info_handle.Get(), NULL, &BluetoothInterfaceGUID, device_index, |
+ &device_interface_data); |
if (!success) { |
HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); |
if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) { |
@@ -509,10 +456,11 @@ DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice( |
return kOk; |
} |
-// Opens a Device Info Set that can be used to enumerate Bluetooth LE devices |
-// present on the machine. |
-HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle) { |
- GUID BluetoothClassGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE; |
+// Opens a Device Info Set that can be used to enumerate Bluetooth LE or Gatt |
+// Service devices present on the machine. |
+HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle, |
+ GUID guid) { |
+ GUID BluetoothClassGUID = guid; |
ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs( |
&BluetoothClassGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); |
if (!result.IsValid()) { |
@@ -558,11 +506,9 @@ DeviceRegistryPropertyValue::DeviceRegistryPropertyValue( |
size_t value_size) |
: property_type_(property_type), |
value_(value.Pass()), |
- value_size_(value_size) { |
-} |
+ value_size_(value_size) {} |
-DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() { |
-} |
+DeviceRegistryPropertyValue::~DeviceRegistryPropertyValue() {} |
std::string DeviceRegistryPropertyValue::AsString() const { |
CHECK_EQ(property_type_, static_cast<DWORD>(REG_SZ)); |
@@ -581,11 +527,9 @@ DevicePropertyValue::DevicePropertyValue(DEVPROPTYPE property_type, |
size_t value_size) |
: property_type_(property_type), |
value_(value.Pass()), |
- value_size_(value_size) { |
-} |
+ value_size_(value_size) {} |
-DevicePropertyValue::~DevicePropertyValue() { |
-} |
+DevicePropertyValue::~DevicePropertyValue() {} |
uint32_t DevicePropertyValue::AsUint32() const { |
CHECK_EQ(property_type_, static_cast<DEVPROPTYPE>(DEVPROP_TYPE_UINT32)); |
@@ -593,25 +537,23 @@ uint32_t DevicePropertyValue::AsUint32() const { |
return *reinterpret_cast<uint32_t*>(value_.get()); |
} |
-BluetoothLowEnergyServiceInfo::BluetoothLowEnergyServiceInfo() { |
-} |
+BluetoothLowEnergyServiceInfo::BluetoothLowEnergyServiceInfo() {} |
-BluetoothLowEnergyServiceInfo::~BluetoothLowEnergyServiceInfo() { |
-} |
+BluetoothLowEnergyServiceInfo::~BluetoothLowEnergyServiceInfo() {} |
BluetoothLowEnergyDeviceInfo::BluetoothLowEnergyDeviceInfo() |
: visible(false), authenticated(false), connected(false) { |
address.ullLong = BLUETOOTH_NULL_ADDRESS; |
} |
-BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() { |
-} |
+BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() {} |
bool IsBluetoothLowEnergySupported() { |
return base::win::GetVersion() >= base::win::VERSION_WIN8; |
} |
bool EnumerateKnownBluetoothLowEnergyDevices( |
+ GUID guid, |
ScopedVector<BluetoothLowEnergyDeviceInfo>* devices, |
std::string* error) { |
if (!IsBluetoothLowEnergySupported()) { |
@@ -620,7 +562,7 @@ bool EnumerateKnownBluetoothLowEnergyDevices( |
} |
ScopedDeviceInfoSetHandle info_set_handle; |
- HRESULT hr = OpenBluetoothLowEnergyDevices(&info_set_handle); |
+ HRESULT hr = OpenBluetoothLowEnergyDevices(&info_set_handle, guid); |
if (FAILED(hr)) { |
*error = FormatBluetoothError(kDeviceEnumError, hr); |
return false; |
@@ -629,7 +571,7 @@ bool EnumerateKnownBluetoothLowEnergyDevices( |
for (DWORD i = 0;; ++i) { |
scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info; |
DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice( |
- info_set_handle, i, &device_info, error); |
+ guid, info_set_handle, i, &device_info, error); |
switch (result) { |
case kNoMoreDevices: |
return true; |
@@ -660,5 +602,245 @@ bool ExtractBluetoothAddressFromDeviceInstanceIdForTesting( |
return ExtractBluetoothAddressFromDeviceInstanceId(instance_id, btha, error); |
} |
+HRESULT ReadPrimaryServicesOfADevice(HANDLE device_handle, |
+ BTH_LE_GATT_SERVICE** out_primary_services, |
+ USHORT* out_counts) { |
+ USHORT required_length = 0; |
+ HRESULT hr = BluetoothGATTGetServices( |
+ device_handle, 0, NULL, &required_length, BLUETOOTH_GATT_FLAG_NONE); |
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { |
+ return hr; |
+ } |
+ |
+ *out_primary_services = new BTH_LE_GATT_SERVICE[required_length]; |
+ USHORT actual_length = required_length; |
+ hr = BluetoothGATTGetServices(device_handle, actual_length, |
+ *out_primary_services, &required_length, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ if (SUCCEEDED(hr) && required_length != actual_length) { |
+ LOG(ERROR) << "Retrieved primary services is not equal to expected" |
+ << " actual_length " << actual_length << " required_length " |
+ << required_length; |
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); |
+ } |
+ |
+ *out_counts = actual_length; |
+ if (FAILED(hr)) { |
+ delete *out_primary_services; |
+ *out_counts = 0; |
+ } |
+ return hr; |
+} |
+ |
+HRESULT ReadCharacteristicsOfAService( |
+ HANDLE device_handle, |
+ const PBTH_LE_GATT_SERVICE service, |
+ BTH_LE_GATT_CHARACTERISTIC** out_included_characteristics, |
+ USHORT* out_counts) { |
+ USHORT required_length = 0; |
+ HRESULT hr = BluetoothGATTGetCharacteristics(device_handle, service, 0, NULL, |
+ &required_length, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { |
+ return hr; |
+ } |
+ |
+ *out_included_characteristics = |
+ new BTH_LE_GATT_CHARACTERISTIC[required_length]; |
+ USHORT actual_length = required_length; |
+ hr = BluetoothGATTGetCharacteristics( |
+ device_handle, service, actual_length, *out_included_characteristics, |
+ &required_length, BLUETOOTH_GATT_FLAG_NONE); |
+ if (SUCCEEDED(hr) && required_length != actual_length) { |
+ LOG(ERROR) << "Retrieved charactersitics is not equal to expected" |
+ << " actual_length " << actual_length << " required_length " |
+ << required_length; |
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); |
+ } |
+ |
+ *out_counts = actual_length; |
+ if (FAILED(hr)) { |
+ delete *out_included_characteristics; |
+ *out_counts = 0; |
+ } |
+ return hr; |
+} |
+ |
+HRESULT ReadIncludedServicesOfAService( |
+ HANDLE device_handle, |
+ const PBTH_LE_GATT_SERVICE service, |
+ BTH_LE_GATT_SERVICE** out_included_services, |
+ USHORT* out_counts) { |
+ USHORT required_length = 0; |
+ HRESULT hr = BluetoothGATTGetIncludedServices(device_handle, service, 0, NULL, |
+ &required_length, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { |
+ return hr; |
+ } |
+ |
+ *out_included_services = new BTH_LE_GATT_SERVICE[required_length]; |
+ USHORT actual_length = required_length; |
+ hr = BluetoothGATTGetIncludedServices( |
+ device_handle, service, actual_length, *out_included_services, |
+ &required_length, BLUETOOTH_GATT_FLAG_NONE); |
+ if (SUCCEEDED(hr) && required_length != actual_length) { |
+ LOG(ERROR) << "Retrieved included services is not equal to expected" |
+ << " actual_length " << actual_length << " required_length " |
+ << required_length; |
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); |
+ } |
+ |
+ *out_counts = actual_length; |
+ if (FAILED(hr)) { |
+ delete *out_included_services; |
+ *out_counts = 0; |
+ } |
+ return hr; |
+} |
+ |
+HRESULT ReadTheValueOfACharacteristic( |
+ HANDLE device_handle, |
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic, |
+ BTH_LE_GATT_CHARACTERISTIC_VALUE** out_characteristic_value) { |
+ USHORT required_length = 0; |
+ HRESULT hr = BluetoothGATTGetCharacteristicValue( |
+ device_handle, characteristic, 0, NULL, &required_length, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { |
+ return hr; |
+ } |
+ |
+ *out_characteristic_value = |
+ (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(new UCHAR[required_length]); |
+ USHORT actual_length = required_length; |
+ hr = BluetoothGATTGetCharacteristicValue( |
+ device_handle, characteristic, (ULONG)required_length, |
+ *out_characteristic_value, &actual_length, BLUETOOTH_GATT_FLAG_NONE); |
+ if (SUCCEEDED(hr) && required_length != actual_length) { |
+ LOG(ERROR) << "Retrieved characteristic value size is not equal to expected" |
+ << " actual_length " << actual_length << " required_length " |
+ << required_length; |
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); |
+ } |
+ |
+ if (FAILED(hr)) { |
+ delete *out_characteristic_value; |
+ } |
+ return hr; |
+} |
+ |
+HRESULT WriteTheValueOfACharacteristic( |
+ HANDLE device_handle, |
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic, |
+ BTH_LE_GATT_CHARACTERISTIC_VALUE* new_value) { |
+ return BluetoothGATTSetCharacteristicValue( |
+ device_handle, characteristic, new_value, NULL, BLUETOOTH_GATT_FLAG_NONE); |
+} |
+ |
+HRESULT ReliableWriteTheValueOfACharacteristic( |
+ HANDLE device_handle, |
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic, |
+ BTH_LE_GATT_CHARACTERISTIC_VALUE* new_value) { |
+ BTH_LE_GATT_RELIABLE_WRITE_CONTEXT reliable_write_context = NULL; |
+ HRESULT hr = BluetoothGATTBeginReliableWrite( |
+ device_handle, &reliable_write_context, BLUETOOTH_GATT_FLAG_NONE); |
+ if (FAILED(hr)) |
+ return hr; |
+ |
+ hr = BluetoothGATTSetCharacteristicValue( |
+ device_handle, characteristic, new_value, NULL, BLUETOOTH_GATT_FLAG_NONE); |
+ if (NULL != reliable_write_context) { |
+ BluetoothGATTEndReliableWrite(device_handle, reliable_write_context, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ } |
+ |
+ return hr; |
+} |
+ |
+HRESULT ReadDescriptorsOfACharacteristic( |
+ HANDLE device_handle, |
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic, |
+ BTH_LE_GATT_DESCRIPTOR** out_included_descriptors, |
+ USHORT* out_counts) { |
+ USHORT required_length = 0; |
+ HRESULT hr = |
+ BluetoothGATTGetDescriptors(device_handle, characteristic, 0, NULL, |
+ &required_length, BLUETOOTH_GATT_FLAG_NONE); |
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { |
+ return hr; |
+ } |
+ |
+ *out_included_descriptors = new BTH_LE_GATT_DESCRIPTOR[required_length]; |
+ USHORT actual_length = required_length; |
+ hr = BluetoothGATTGetDescriptors(device_handle, characteristic, actual_length, |
+ *out_included_descriptors, &required_length, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ if (SUCCEEDED(hr) && required_length != actual_length) { |
+ LOG(ERROR) << "Retrieved # of descriptors is not equal to expected" |
+ << " actual_length " << actual_length << " required_length " |
+ << required_length; |
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); |
+ } |
+ |
+ *out_counts = actual_length; |
+ if (FAILED(hr)) { |
+ delete *out_included_descriptors; |
+ *out_counts = 0; |
+ } |
+ return hr; |
+} |
+ |
+HRESULT ReadTheValueOfADescriptor(HANDLE device_handle, |
+ const PBTH_LE_GATT_DESCRIPTOR descriptor, |
+ BTH_LE_GATT_DESCRIPTOR_VALUE** out_value) { |
+ USHORT required_length = 0; |
+ HRESULT hr = BluetoothGATTGetDescriptorValue(device_handle, descriptor, 0, |
+ NULL, &required_length, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { |
+ return hr; |
+ } |
+ |
+ *out_value = (PBTH_LE_GATT_DESCRIPTOR_VALUE)(new UCHAR[required_length]); |
+ USHORT actual_length = required_length; |
+ hr = BluetoothGATTGetDescriptorValue( |
+ device_handle, descriptor, (ULONG)actual_length, *out_value, |
+ &required_length, BLUETOOTH_GATT_FLAG_NONE); |
+ if (SUCCEEDED(hr) && required_length != actual_length) { |
+ LOG(ERROR) << "Retrieved descriptor value size is not equal to expected" |
+ << " actual_length " << actual_length << " required_length " |
+ << required_length; |
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); |
+ } |
+ |
+ if (FAILED(hr)) { |
+ delete *out_value; |
+ } |
+ return hr; |
+} |
+ |
+HRESULT WriteTheDescriptorValue(HANDLE device_handle, |
+ const PBTH_LE_GATT_DESCRIPTOR descriptor, |
+ BTH_LE_GATT_DESCRIPTOR_VALUE* new_value) { |
+ return BluetoothGATTSetDescriptorValue(device_handle, descriptor, new_value, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+} |
+ |
+HRESULT RegisterGattEvents(HANDLE device_handle, |
+ BTH_LE_GATT_EVENT_TYPE type, |
+ PVOID event_parameter, |
+ PFNBLUETOOTH_GATT_EVENT_CALLBACK callback, |
+ PVOID context, |
+ BLUETOOTH_GATT_EVENT_HANDLE* out_handle) { |
+ return BluetoothGATTRegisterEvent(device_handle, type, event_parameter, |
+ callback, context, out_handle, |
+ BLUETOOTH_GATT_FLAG_NONE); |
+} |
+ |
+HRESULT UnregisterGattEvent(BLUETOOTH_GATT_EVENT_HANDLE event_handle) { |
+ return BluetoothGATTUnregisterEvent(event_handle, BLUETOOTH_GATT_FLAG_NONE); |
+} |
+ |
} // namespace win |
} // namespace device |