Index: device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm |
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm |
index 20f696ea2ea6819cdc3867700b57444c9d169935..e54a7c5fab99c24ffde3a53c8ad0466110a954e9 100644 |
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm |
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm |
@@ -162,11 +162,41 @@ void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic( |
const std::vector<uint8_t>& new_value, |
const base::Closure& callback, |
const ErrorCallback& error_callback) { |
- NOTIMPLEMENTED(); |
+ if (!IsWritable()) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(error_callback, |
+ BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED)); |
+ return; |
+ } |
+ if (characteristic_value_read_or_write_in_progress_) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(error_callback, |
+ BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); |
+ return; |
+ } |
+ characteristic_value_read_or_write_in_progress_ = true; |
+ write_characteristic_value_callbacks_ = |
+ std::make_pair(callback, error_callback); |
+ base::scoped_nsobject<NSData> nsdata_value( |
+ [[NSData alloc] initWithBytes:new_value.data() length:new_value.size()]); |
+ CBCharacteristicWriteType write_type = GetCBWriteType(); |
+ [gatt_service_->GetCBPeripheral() writeValue:nsdata_value |
+ forCharacteristic:cb_characteristic_ |
+ type:write_type]; |
+ if (write_type == CBCharacteristicWriteWithoutResponse) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&BluetoothRemoteGattCharacteristicMac::DidWriteValue, |
+ base::Unretained(this), nil)); |
+ } |
} |
void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { |
if (!characteristic_value_read_or_write_in_progress_) { |
+ // In case of buggy device, nothing should be done if receiving extra |
+ // read confirmation. |
return; |
} |
std::pair<ValueCallback, ErrorCallback> callbacks; |
@@ -188,13 +218,50 @@ void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { |
callbacks.first.Run(value_); |
} |
+void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { |
+ if (!characteristic_value_read_or_write_in_progress_) { |
+ // In case of buggy device, nothing should be done if receiving extra |
+ // write confirmation. |
+ return; |
+ } |
+ std::pair<base::Closure, ErrorCallback> callbacks; |
+ callbacks.swap(write_characteristic_value_callbacks_); |
+ characteristic_value_read_or_write_in_progress_ = false; |
+ if (error) { |
+ VLOG(1) << "Bluetooth error while reading for characteristic, domain: " |
+ << error.domain.UTF8String << ", error code: " << error.code; |
+ BluetoothGattService::GattErrorCode error_code = |
+ BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); |
+ callbacks.second.Run(error_code); |
+ return; |
+ } |
+ NSData* nsdata_value = cb_characteristic_.get().value; |
+ const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); |
+ std::vector<uint8_t> gatt_value(buffer, buffer + nsdata_value.length); |
+ gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged(this, |
+ value_); |
+ callbacks.first.Run(); |
+} |
+ |
bool BluetoothRemoteGattCharacteristicMac::IsReadable() const { |
return GetProperties() & BluetoothGattCharacteristic::PROPERTY_READ; |
} |
+bool BluetoothRemoteGattCharacteristicMac::IsWritable() const { |
+ BluetoothGattCharacteristic::Properties properties = GetProperties(); |
+ return (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) || |
+ (properties & PROPERTY_WRITE_WITHOUT_RESPONSE); |
+} |
+ |
+CBCharacteristicWriteType BluetoothRemoteGattCharacteristicMac::GetCBWriteType() |
+ const { |
+ return (GetProperties() & BluetoothGattCharacteristic::PROPERTY_WRITE) |
+ ? CBCharacteristicWriteWithResponse |
+ : CBCharacteristicWriteWithoutResponse; |
+} |
+ |
CBCharacteristic* BluetoothRemoteGattCharacteristicMac::GetCBCharacteristic() |
const { |
return cb_characteristic_.get(); |
} |
- |
} // namespace device. |