| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/bluetooth/bluetooth_device_chromeos.h" | 5 #include "device/bluetooth/bluetooth_device_chromeos.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 using device::BluetoothSocket; | 39 using device::BluetoothSocket; |
| 40 | 40 |
| 41 namespace chromeos { | 41 namespace chromeos { |
| 42 | 42 |
| 43 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS( | 43 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS( |
| 44 BluetoothAdapterChromeOS* adapter) | 44 BluetoothAdapterChromeOS* adapter) |
| 45 : BluetoothDevice(), | 45 : BluetoothDevice(), |
| 46 adapter_(adapter), | 46 adapter_(adapter), |
| 47 pairing_delegate_(NULL), | 47 pairing_delegate_(NULL), |
| 48 connecting_applications_counter_(0), | 48 connecting_applications_counter_(0), |
| 49 service_records_loaded_(false), |
| 49 weak_ptr_factory_(this) { | 50 weak_ptr_factory_(this) { |
| 50 } | 51 } |
| 51 | 52 |
| 52 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { | 53 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { |
| 53 } | 54 } |
| 54 | 55 |
| 55 bool BluetoothDeviceChromeOS::IsPaired() const { | 56 bool BluetoothDeviceChromeOS::IsPaired() const { |
| 56 return !object_path_.value().empty(); | 57 return !object_path_.value().empty(); |
| 57 } | 58 } |
| 58 | 59 |
| 59 const BluetoothDevice::ServiceList& | 60 const BluetoothDevice::ServiceList& |
| 60 BluetoothDeviceChromeOS::GetServices() const { | 61 BluetoothDeviceChromeOS::GetServices() const { |
| 61 return service_uuids_; | 62 return service_uuids_; |
| 62 } | 63 } |
| 63 | 64 |
| 64 void BluetoothDeviceChromeOS::GetServiceRecords( | 65 void BluetoothDeviceChromeOS::GetServiceRecords( |
| 65 const ServiceRecordsCallback& callback, | 66 const ServiceRecordsCallback& callback, |
| 66 const ErrorCallback& error_callback) { | 67 const ErrorCallback& error_callback) { |
| 67 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> | 68 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> |
| 68 DiscoverServices( | 69 DiscoverServices( |
| 69 object_path_, | 70 object_path_, |
| 70 "", // empty pattern to browse all services | 71 "", // empty pattern to browse all services |
| 71 base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback, | 72 base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback, |
| 72 weak_ptr_factory_.GetWeakPtr(), | 73 weak_ptr_factory_.GetWeakPtr(), |
| 73 callback, | 74 callback, |
| 74 error_callback)); | 75 base::Bind( |
| 76 &BluetoothDeviceChromeOS::OnGetServiceRecordsError, |
| 77 weak_ptr_factory_.GetWeakPtr(), |
| 78 callback, |
| 79 error_callback))); |
| 75 } | 80 } |
| 76 | 81 |
| 77 bool BluetoothDeviceChromeOS::ProvidesServiceWithUUID( | 82 bool BluetoothDeviceChromeOS::ProvidesServiceWithUUID( |
| 78 const std::string& uuid) const { | 83 const std::string& uuid) const { |
| 79 const BluetoothDevice::ServiceList& services = GetServices(); | 84 const BluetoothDevice::ServiceList& services = GetServices(); |
| 80 for (BluetoothDevice::ServiceList::const_iterator iter = services.begin(); | 85 for (BluetoothDevice::ServiceList::const_iterator iter = services.begin(); |
| 81 iter != services.end(); | 86 iter != services.end(); |
| 82 ++iter) { | 87 ++iter) { |
| 83 if (device::bluetooth_utils::CanonicalUuid(*iter) == uuid) | 88 if (device::bluetooth_utils::CanonicalUuid(*iter) == uuid) |
| 84 return true; | 89 return true; |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 | 367 |
| 363 // Mark the device trusted so it can connect to us automatically, and | 368 // Mark the device trusted so it can connect to us automatically, and |
| 364 // we can connect after rebooting. This information is part of the | 369 // we can connect after rebooting. This information is part of the |
| 365 // pairing information of the device, and is unique to the combination | 370 // pairing information of the device, and is unique to the combination |
| 366 // of our bluetooth address and the device's bluetooth address. A | 371 // of our bluetooth address and the device's bluetooth address. A |
| 367 // different host needs a new pairing, so it's not useful to sync. | 372 // different host needs a new pairing, so it's not useful to sync. |
| 368 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> | 373 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> |
| 369 GetProperties(object_path_)->trusted.Set( | 374 GetProperties(object_path_)->trusted.Set( |
| 370 true, | 375 true, |
| 371 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted, | 376 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted, |
| 372 weak_ptr_factory_.GetWeakPtr(), | 377 weak_ptr_factory_.GetWeakPtr())); |
| 373 callback, | |
| 374 base::Bind(error_callback, | |
| 375 ERROR_UNKNOWN))); | |
| 376 // TODO(deymo): Replace ERROR_UNKNOWN with an appropriate new constant. | |
| 377 | 378 |
| 378 // Connect application-layer protocols. | 379 // In parallel with the |trusted| property change, call GetServiceRecords to |
| 379 ConnectApplications(callback, error_callback); | 380 // retrieve the SDP from the device and then, either on success or failure, |
| 381 // call ConnectApplications. |
| 382 GetServiceRecords( |
| 383 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecords, |
| 384 weak_ptr_factory_.GetWeakPtr(), |
| 385 callback, |
| 386 error_callback), |
| 387 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError, |
| 388 weak_ptr_factory_.GetWeakPtr(), |
| 389 callback, |
| 390 error_callback)); |
| 380 } | 391 } |
| 381 | 392 |
| 382 void BluetoothDeviceChromeOS::OnCreateDeviceError( | 393 void BluetoothDeviceChromeOS::OnCreateDeviceError( |
| 383 const ConnectErrorCallback& error_callback, | 394 const ConnectErrorCallback& error_callback, |
| 384 const std::string& error_name, | 395 const std::string& error_name, |
| 385 const std::string& error_message) { | 396 const std::string& error_message) { |
| 386 // The default |error_code| is an unknown error. | 397 // The default |error_code| is an unknown error. |
| 387 ConnectErrorCode error_code = ERROR_UNKNOWN; | 398 ConnectErrorCode error_code = ERROR_UNKNOWN; |
| 388 | 399 |
| 389 // Report any error in the log, even if we know the possible source of it. | 400 // Report any error in the log, even if we know the possible source of it. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 409 const ServiceRecordsCallback& callback, | 420 const ServiceRecordsCallback& callback, |
| 410 const ErrorCallback& error_callback, | 421 const ErrorCallback& error_callback, |
| 411 const dbus::ObjectPath& device_path, | 422 const dbus::ObjectPath& device_path, |
| 412 const BluetoothDeviceClient::ServiceMap& service_map, | 423 const BluetoothDeviceClient::ServiceMap& service_map, |
| 413 bool success) { | 424 bool success) { |
| 414 if (!success) { | 425 if (!success) { |
| 415 error_callback.Run(); | 426 error_callback.Run(); |
| 416 return; | 427 return; |
| 417 } | 428 } |
| 418 | 429 |
| 419 ScopedVector<BluetoothServiceRecord> records; | 430 // Update the cache. No other thread is executing a GetServiceRecords |
| 431 // callback, so it is safe to delete the previous objects here. |
| 432 service_records_.clear(); |
| 433 // TODO(deymo): Perhaps don't update the cache if the new SDP information is |
| 434 // empty and we had something before. Some devices only answer this |
| 435 // information while paired, and this callback could be called in any order if |
| 436 // several calls to GetServiceRecords are made while initial pairing with the |
| 437 // device. This requires more investigation. |
| 420 for (BluetoothDeviceClient::ServiceMap::const_iterator i = | 438 for (BluetoothDeviceClient::ServiceMap::const_iterator i = |
| 421 service_map.begin(); i != service_map.end(); ++i) { | 439 service_map.begin(); i != service_map.end(); ++i) { |
| 422 records.push_back( | 440 service_records_.push_back( |
| 423 new BluetoothServiceRecordChromeOS(address(), i->second)); | 441 new BluetoothServiceRecordChromeOS(address(), i->second)); |
| 424 } | 442 } |
| 425 callback.Run(records); | 443 service_records_loaded_ = true; |
| 444 OnServiceRecordsChanged(); |
| 445 |
| 446 callback.Run(service_records_); |
| 426 } | 447 } |
| 427 | 448 |
| 428 void BluetoothDeviceChromeOS::OnSetTrusted(const base::Closure& callback, | 449 void BluetoothDeviceChromeOS::OnServiceRecordsChanged(void) { |
| 429 const ErrorCallback& error_callback, | 450 // Update the BluetoothDevice::connectable_ property. |
| 430 bool success) { | 451 bool hid_normally_connectable = true; |
| 431 if (success) { | 452 bool hid_reconnect_initiate = true; |
| 432 callback.Run(); | 453 for (ServiceRecordList::const_iterator it = service_records_.begin(); |
| 454 it != service_records_.end(); ++it) { |
| 455 if ((*it)->SupportsHid()) { |
| 456 // If there are several HID profiles, we assume the device is connectable |
| 457 // if all them are connectable. |
| 458 hid_normally_connectable = |
| 459 hid_normally_connectable && (*it)->hid_normally_connectable(); |
| 460 hid_reconnect_initiate = |
| 461 hid_reconnect_initiate && (*it)->hid_reconnect_initiate(); |
| 462 } |
| 463 } |
| 464 // The Bluetooth HID spec states that if HIDNormallyConnectable or |
| 465 // HIDReconnectInitiate are not present in a HID profile, the value is false. |
| 466 // Nevertheless, a device with both properties in false can't reconnect to the |
| 467 // adapter and can't be reconnected from the adapter. To avoid problems with |
| 468 // devices that don't export this properties we asume they are connectable. |
| 469 connectable_ = hid_normally_connectable || !hid_reconnect_initiate; |
| 470 DVLOG(1) << "ServiceRecordsChanged for " << address_ |
| 471 << ": connectable = " << connectable_; |
| 472 } |
| 473 |
| 474 void BluetoothDeviceChromeOS::OnSetTrusted(bool success) { |
| 475 LOG_IF(WARNING, !success) << "Failed to set device as trusted: " << address_; |
| 476 } |
| 477 |
| 478 void BluetoothDeviceChromeOS::OnInitialGetServiceRecords( |
| 479 const base::Closure& callback, |
| 480 const ConnectErrorCallback& error_callback, |
| 481 const ServiceRecordList& list) { |
| 482 // Connect application-layer protocols. |
| 483 ConnectApplications(callback, error_callback); |
| 484 } |
| 485 |
| 486 void BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError( |
| 487 const base::Closure& callback, |
| 488 const ConnectErrorCallback& error_callback) { |
| 489 // Ignore the error retrieving the service records and continue. |
| 490 LOG(WARNING) << "Error retrieving SDP for " << address_ << " after pairing."; |
| 491 // Connect application-layer protocols. |
| 492 ConnectApplications(callback, error_callback); |
| 493 } |
| 494 |
| 495 void BluetoothDeviceChromeOS::OnGetServiceRecordsError( |
| 496 const ServiceRecordsCallback& callback, |
| 497 const ErrorCallback& error_callback) { |
| 498 if (service_records_loaded_) { |
| 499 callback.Run(service_records_); |
| 433 } else { | 500 } else { |
| 434 LOG(WARNING) << "Failed to set device as trusted: " << address_; | |
| 435 error_callback.Run(); | 501 error_callback.Run(); |
| 436 } | 502 } |
| 437 } | 503 } |
| 438 | 504 |
| 439 void BluetoothDeviceChromeOS::ConnectApplications( | 505 void BluetoothDeviceChromeOS::ConnectApplications( |
| 440 const base::Closure& callback, | 506 const base::Closure& callback, |
| 441 const ConnectErrorCallback& error_callback) { | 507 const ConnectErrorCallback& error_callback) { |
| 442 // Introspect the device object to determine supported applications. | 508 // Introspect the device object to determine supported applications. |
| 443 DBusThreadManager::Get()->GetIntrospectableClient()-> | 509 DBusThreadManager::Get()->GetIntrospectableClient()-> |
| 444 Introspect(bluetooth_device::kBluetoothDeviceServiceName, | 510 Introspect(bluetooth_device::kBluetoothDeviceServiceName, |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 } | 808 } |
| 743 | 809 |
| 744 | 810 |
| 745 // static | 811 // static |
| 746 BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create( | 812 BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create( |
| 747 BluetoothAdapterChromeOS* adapter) { | 813 BluetoothAdapterChromeOS* adapter) { |
| 748 return new BluetoothDeviceChromeOS(adapter); | 814 return new BluetoothDeviceChromeOS(adapter); |
| 749 } | 815 } |
| 750 | 816 |
| 751 } // namespace chromeos | 817 } // namespace chromeos |
| OLD | NEW |