Home | History | Annotate | Download | only in nfc
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "device/nfc/nfc_adapter_chromeos.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/callback.h"
     10 #include "base/logging.h"
     11 #include "chromeos/dbus/dbus_thread_manager.h"
     12 #include "device/nfc/nfc_peer.h"
     13 #include "device/nfc/nfc_tag.h"
     14 #include "third_party/cros_system_api/dbus/service_constants.h"
     15 
     16 namespace chromeos {
     17 
     18 NfcAdapterChromeOS::NfcAdapterChromeOS()
     19     : weak_ptr_factory_(this) {
     20   DBusThreadManager::Get()->GetNfcAdapterClient()->AddObserver(this);
     21   DBusThreadManager::Get()->GetNfcDeviceClient()->AddObserver(this);
     22   DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this);
     23 
     24   const std::vector<dbus::ObjectPath>& object_paths =
     25       DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters();
     26   if (!object_paths.empty()) {
     27     VLOG(1) << object_paths.size() << " NFC adapter(s) available.";
     28     SetAdapter(object_paths[0]);
     29   }
     30 }
     31 
     32 NfcAdapterChromeOS::~NfcAdapterChromeOS() {
     33   DBusThreadManager::Get()->GetNfcAdapterClient()->RemoveObserver(this);
     34   DBusThreadManager::Get()->GetNfcDeviceClient()->RemoveObserver(this);
     35   DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this);
     36 }
     37 
     38 void NfcAdapterChromeOS::AddObserver(NfcAdapter::Observer* observer) {
     39   DCHECK(observer);
     40   observers_.AddObserver(observer);
     41 }
     42 
     43 void NfcAdapterChromeOS::RemoveObserver(NfcAdapter::Observer* observer) {
     44   DCHECK(observer);
     45   observers_.RemoveObserver(observer);
     46 }
     47 
     48 bool NfcAdapterChromeOS::IsPresent() const {
     49   return !object_path_.value().empty();
     50 }
     51 
     52 bool NfcAdapterChromeOS::IsPowered() const {
     53   if (!IsPresent())
     54     return false;
     55   return DBusThreadManager::Get()->GetNfcAdapterClient()->
     56       GetProperties(object_path_)->powered.value();
     57 }
     58 
     59 bool NfcAdapterChromeOS::IsPolling() const {
     60   if (!IsPresent())
     61     return false;
     62   return DBusThreadManager::Get()->GetNfcAdapterClient()->
     63       GetProperties(object_path_)->polling.value();
     64 }
     65 
     66 bool NfcAdapterChromeOS::IsInitialized() const {
     67   return true;
     68 }
     69 
     70 void NfcAdapterChromeOS::SetPowered(bool powered,
     71                                     const base::Closure& callback,
     72                                     const ErrorCallback& error_callback) {
     73   if (!IsPresent()) {
     74     LOG(WARNING) << "Adapter not present. Cannot power up the antenna.";
     75     error_callback.Run();
     76     return;
     77   }
     78   DBusThreadManager::Get()->GetNfcAdapterClient()->
     79       GetProperties(object_path_)->powered.Set(
     80           powered,
     81           base::Bind(&NfcAdapterChromeOS::OnSetPowered,
     82                      weak_ptr_factory_.GetWeakPtr(),
     83                      callback,
     84                      error_callback));
     85 }
     86 
     87 void NfcAdapterChromeOS::StartPolling(const base::Closure& callback,
     88                                       const ErrorCallback& error_callback) {
     89   // Always poll in "Initiator" mode.
     90   DBusThreadManager::Get()->GetNfcAdapterClient()->
     91       StartPollLoop(object_path_,
     92                     nfc_adapter::kModeInitiator,
     93                     base::Bind(&NfcAdapterChromeOS::OnStartPolling,
     94                                weak_ptr_factory_.GetWeakPtr(),
     95                                callback),
     96                     base::Bind(&NfcAdapterChromeOS::OnStartPollingError,
     97                                weak_ptr_factory_.GetWeakPtr(),
     98                                error_callback));
     99 }
    100 
    101 void NfcAdapterChromeOS::StopPolling(const base::Closure& callback,
    102                                      const ErrorCallback& error_callback) {
    103   DBusThreadManager::Get()->GetNfcAdapterClient()->
    104       StopPollLoop(object_path_,
    105                    base::Bind(&NfcAdapterChromeOS::OnStopPolling,
    106                               weak_ptr_factory_.GetWeakPtr(),
    107                               callback),
    108                    base::Bind(&NfcAdapterChromeOS::OnStopPollingError,
    109                               weak_ptr_factory_.GetWeakPtr(),
    110                               error_callback));
    111 }
    112 
    113 void NfcAdapterChromeOS::AdapterAdded(const dbus::ObjectPath& object_path) {
    114   // Set the adapter to the newly added adapter only if no adapter is present.
    115   if (!IsPresent())
    116     SetAdapter(object_path);
    117 }
    118 
    119 void NfcAdapterChromeOS::AdapterRemoved(const dbus::ObjectPath& object_path) {
    120   if (object_path != object_path_)
    121     return;
    122 
    123   // The current adapter was removed, so mark us as not present and clean up
    124   // peers and tags.
    125   RemoveAdapter();
    126 
    127   // There may still be other adapters present on the system. Set the next
    128   // available adapter as the current one.
    129   const std::vector<dbus::ObjectPath>& object_paths =
    130       DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters();
    131   for (std::vector<dbus::ObjectPath>::const_iterator iter =
    132           object_paths.begin();
    133        iter != object_paths.end(); ++iter) {
    134     // The removed object will still be available until the call to
    135     // AdapterRemoved returns. Make sure that we are not re-adding the
    136     // removed adapter.
    137     if (*iter == object_path)
    138       continue;
    139     SetAdapter(*iter);
    140   }
    141 }
    142 
    143 void NfcAdapterChromeOS::AdapterPropertyChanged(
    144     const dbus::ObjectPath& object_path,
    145     const std::string& property_name) {
    146   if (object_path != object_path_)
    147     return;
    148   NfcAdapterClient::Properties* properties =
    149       DBusThreadManager::Get()->GetNfcAdapterClient()->
    150           GetProperties(object_path_);
    151   if (property_name == properties->powered.name())
    152     PoweredChanged(properties->powered.value());
    153   else if (property_name == properties->polling.name())
    154     PollingChanged(properties->polling.value());
    155 }
    156 
    157 void NfcAdapterChromeOS::DeviceAdded(const dbus::ObjectPath& object_path) {
    158   VLOG(1) << "NFC device found: " << object_path.value();
    159   // TODO(armansito): Implement device logic.
    160 }
    161 
    162 void NfcAdapterChromeOS::DeviceRemoved(const dbus::ObjectPath& object_path) {
    163   VLOG(1) << "NFC device lost: " << object_path.value();
    164   // TODO(armansito): Implement device logic.
    165 }
    166 
    167 void NfcAdapterChromeOS::DevicePropertyChanged(
    168     const dbus::ObjectPath& object_path,
    169     const std::string& property_name) {
    170   // TODO(armansito): Implement device logic.
    171 }
    172 
    173 void NfcAdapterChromeOS::TagAdded(const dbus::ObjectPath& object_path) {
    174   VLOG(1) << "NFC tag found: " << object_path.value();
    175   // TODO(armansito): Implement tag logic.
    176 }
    177 
    178 void NfcAdapterChromeOS::TagRemoved(const dbus::ObjectPath& object_path) {
    179   VLOG(1) << "NFC tag found: " << object_path.value();
    180   // TODO(armansito): Implement tag logic.
    181 }
    182 
    183 void NfcAdapterChromeOS::TagPropertyChanged(
    184     const dbus::ObjectPath& object_path,
    185     const std::string& property_name) {
    186   // TODO(armansito): Implement tag logic.
    187 }
    188 
    189 void NfcAdapterChromeOS::SetAdapter(const dbus::ObjectPath& object_path) {
    190   DCHECK(!IsPresent());
    191   object_path_ = object_path;
    192   VLOG(1) << "Using NFC adapter: " << object_path.value();
    193 
    194   NfcAdapterClient::Properties* properties =
    195       DBusThreadManager::Get()->GetNfcAdapterClient()->
    196           GetProperties(object_path_);
    197   PresentChanged(true);
    198   if (properties->powered.value())
    199     PoweredChanged(true);
    200   if (properties->polling.value())
    201     PollingChanged(true);
    202 
    203   // TODO(armansito): Create device::NfcPeer and device::NfcTag instances for
    204   // all peers and tags that exist, once they have been implemented for
    205   // ChromeOS.
    206 }
    207 
    208 void NfcAdapterChromeOS::RemoveAdapter() {
    209   DCHECK(IsPresent());
    210   VLOG(1) << "NFC adapter removed: " << object_path_.value();
    211 
    212   NfcAdapterClient::Properties* properties =
    213       DBusThreadManager::Get()->GetNfcAdapterClient()->
    214           GetProperties(object_path_);
    215   if (properties->powered.value())
    216     PoweredChanged(false);
    217   if (properties->polling.value())
    218     PollingChanged(false);
    219 
    220   // Copy the tags and peers here and clear the original containers so that
    221   // GetPeers and GetTags return no values during the *Removed observer calls.
    222   PeersMap peers = peers_;
    223   TagsMap tags = tags_;
    224   peers_.clear();
    225   tags_.clear();
    226 
    227   for (PeersMap::iterator iter = peers_.begin();
    228        iter != peers_.end(); ++iter) {
    229     FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
    230                       PeerLost(this, iter->second));
    231     delete iter->second;
    232   }
    233   for (TagsMap::iterator iter = tags_.begin();
    234        iter != tags_.end(); ++iter) {
    235     FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
    236                       TagLost(this, iter->second));
    237     delete iter->second;
    238   }
    239 
    240   object_path_ = dbus::ObjectPath("");
    241   PresentChanged(false);
    242 }
    243 
    244 void NfcAdapterChromeOS::PoweredChanged(bool powered) {
    245   FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
    246                     AdapterPoweredChanged(this, powered));
    247 }
    248 
    249 void NfcAdapterChromeOS::PollingChanged(bool polling) {
    250   FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
    251                     AdapterPollingChanged(this, polling));
    252 }
    253 
    254 void NfcAdapterChromeOS::PresentChanged(bool present) {
    255   FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_,
    256                     AdapterPresentChanged(this, present));
    257 }
    258 
    259 void NfcAdapterChromeOS::OnSetPowered(const base::Closure& callback,
    260                                       const ErrorCallback& error_callback,
    261                                       bool success) {
    262   VLOG(1) << "NfcAdapterChromeOS::OnSetPowered result: " << success;
    263   if (success) {
    264     // TODO(armansito): There is a bug in neard 0.13 that causes it not to emit
    265     // a signal when the "Powered" property changes. Sync the properties here,
    266     // but remove it in neard 0.14.
    267     if (IsPresent()) {
    268       DBusThreadManager::Get()->GetNfcAdapterClient()->
    269           GetProperties(object_path_)->GetAll();
    270     }
    271     callback.Run();
    272   } else {
    273     LOG(WARNING) << "Failed to power up the NFC antenna radio.";
    274     error_callback.Run();
    275   }
    276 }
    277 
    278 void NfcAdapterChromeOS::OnStartPolling(const base::Closure& callback) {
    279   callback.Run();
    280 }
    281 
    282 void NfcAdapterChromeOS::OnStartPollingError(
    283     const ErrorCallback& error_callback,
    284     const std::string& error_name,
    285     const std::string& error_message) {
    286   LOG(WARNING) << object_path_.value() << ": Failed to start polling: "
    287                << error_name << ": " << error_message;
    288   error_callback.Run();
    289 }
    290 
    291 void NfcAdapterChromeOS::OnStopPolling(const base::Closure& callback) {
    292   callback.Run();
    293 }
    294 
    295 void NfcAdapterChromeOS::OnStopPollingError(
    296     const ErrorCallback& error_callback,
    297     const std::string& error_name,
    298     const std::string& error_message) {
    299   LOG(WARNING) << object_path_.value() << ": Failed to stop polling: "
    300                << error_name << ": " << error_message;
    301   error_callback.Run();
    302 }
    303 
    304 }  // namespace chromeos
    305