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.
5 #include "device/nfc/nfc_adapter_chromeos.h"
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
12 #include "device/nfc/nfc_peer_chromeos.h"
13 #include "device/nfc/nfc_tag_chromeos.h"
14 #include "third_party/cros_system_api/dbus/service_constants.h"
20 typedef std::vector
<dbus::ObjectPath
> ObjectPathVector
;
24 NfcAdapterChromeOS::NfcAdapterChromeOS()
25 : weak_ptr_factory_(this) {
26 DBusThreadManager::Get()->GetNfcAdapterClient()->AddObserver(this);
27 DBusThreadManager::Get()->GetNfcDeviceClient()->AddObserver(this);
28 DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this);
30 const ObjectPathVector
& object_paths
=
31 DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters();
32 if (!object_paths
.empty()) {
33 VLOG(1) << object_paths
.size() << " NFC adapter(s) available.";
34 SetAdapter(object_paths
[0]);
38 NfcAdapterChromeOS::~NfcAdapterChromeOS() {
39 DBusThreadManager::Get()->GetNfcAdapterClient()->RemoveObserver(this);
40 DBusThreadManager::Get()->GetNfcDeviceClient()->RemoveObserver(this);
41 DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this);
44 void NfcAdapterChromeOS::AddObserver(NfcAdapter::Observer
* observer
) {
46 observers_
.AddObserver(observer
);
49 void NfcAdapterChromeOS::RemoveObserver(NfcAdapter::Observer
* observer
) {
51 observers_
.RemoveObserver(observer
);
54 bool NfcAdapterChromeOS::IsPresent() const {
55 return !object_path_
.value().empty();
58 bool NfcAdapterChromeOS::IsPowered() const {
61 return DBusThreadManager::Get()->GetNfcAdapterClient()->
62 GetProperties(object_path_
)->powered
.value();
65 bool NfcAdapterChromeOS::IsPolling() const {
68 return DBusThreadManager::Get()->GetNfcAdapterClient()->
69 GetProperties(object_path_
)->polling
.value();
72 bool NfcAdapterChromeOS::IsInitialized() const {
76 void NfcAdapterChromeOS::SetPowered(bool powered
,
77 const base::Closure
& callback
,
78 const ErrorCallback
& error_callback
) {
80 LOG(WARNING
) << "Adapter not present. Cannot power up the antenna.";
84 DBusThreadManager::Get()->GetNfcAdapterClient()->
85 GetProperties(object_path_
)->powered
.Set(
87 base::Bind(&NfcAdapterChromeOS::OnSetPowered
,
88 weak_ptr_factory_
.GetWeakPtr(),
93 void NfcAdapterChromeOS::StartPolling(const base::Closure
& callback
,
94 const ErrorCallback
& error_callback
) {
95 // Always poll in "Initiator" mode.
96 DBusThreadManager::Get()->GetNfcAdapterClient()->
97 StartPollLoop(object_path_
,
98 nfc_adapter::kModeInitiator
,
99 base::Bind(&NfcAdapterChromeOS::OnStartPolling
,
100 weak_ptr_factory_
.GetWeakPtr(),
102 base::Bind(&NfcAdapterChromeOS::OnStartPollingError
,
103 weak_ptr_factory_
.GetWeakPtr(),
107 void NfcAdapterChromeOS::StopPolling(const base::Closure
& callback
,
108 const ErrorCallback
& error_callback
) {
109 DBusThreadManager::Get()->GetNfcAdapterClient()->
110 StopPollLoop(object_path_
,
111 base::Bind(&NfcAdapterChromeOS::OnStopPolling
,
112 weak_ptr_factory_
.GetWeakPtr(),
114 base::Bind(&NfcAdapterChromeOS::OnStopPollingError
,
115 weak_ptr_factory_
.GetWeakPtr(),
119 void NfcAdapterChromeOS::AdapterAdded(const dbus::ObjectPath
& object_path
) {
120 // Set the adapter to the newly added adapter only if no adapter is present.
122 SetAdapter(object_path
);
125 void NfcAdapterChromeOS::AdapterRemoved(const dbus::ObjectPath
& object_path
) {
126 if (object_path
!= object_path_
)
129 // The current adapter was removed, so mark us as not present and clean up
133 // There may still be other adapters present on the system. Set the next
134 // available adapter as the current one.
135 const ObjectPathVector
& object_paths
=
136 DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters();
137 for (ObjectPathVector::const_iterator iter
=
138 object_paths
.begin();
139 iter
!= object_paths
.end(); ++iter
) {
140 // The removed object will still be available until the call to
141 // AdapterRemoved returns. Make sure that we are not re-adding the
143 if (*iter
== object_path
)
149 void NfcAdapterChromeOS::AdapterPropertyChanged(
150 const dbus::ObjectPath
& object_path
,
151 const std::string
& property_name
) {
152 if (object_path
!= object_path_
)
154 NfcAdapterClient::Properties
* properties
=
155 DBusThreadManager::Get()->GetNfcAdapterClient()->
156 GetProperties(object_path_
);
157 if (property_name
== properties
->powered
.name())
158 PoweredChanged(properties
->powered
.value());
159 else if (property_name
== properties
->polling
.name())
160 PollingChanged(properties
->polling
.value());
163 void NfcAdapterChromeOS::DeviceAdded(const dbus::ObjectPath
& object_path
) {
167 if (GetPeer(object_path
.value()))
170 VLOG(1) << "NFC device found: " << object_path
.value();
172 // Check to see if the device belongs to this adapter.
173 const ObjectPathVector
& devices
=
174 DBusThreadManager::Get()->GetNfcDeviceClient()->
175 GetDevicesForAdapter(object_path_
);
176 bool device_found
= false;
177 for (ObjectPathVector::const_iterator iter
= devices
.begin();
178 iter
!= devices
.end(); ++iter
) {
179 if (*iter
== object_path
) {
185 VLOG(1) << "Found peer device does not belong to the current adapter.";
189 // Create the peer object.
190 NfcPeerChromeOS
* peer_chromeos
= new NfcPeerChromeOS(object_path
);
191 SetPeer(object_path
.value(), peer_chromeos
);
192 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
193 PeerFound(this, peer_chromeos
));
196 void NfcAdapterChromeOS::DeviceRemoved(const dbus::ObjectPath
& object_path
) {
197 VLOG(1) << "NFC device lost: " << object_path
.value();
198 device::NfcPeer
* peer
= RemovePeer(object_path
.value());
200 VLOG(1) << "Removed peer device does not belong to the current adapter.";
203 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
, PeerLost(this, peer
));
207 void NfcAdapterChromeOS::TagAdded(const dbus::ObjectPath
& object_path
) {
211 if (GetTag(object_path
.value()))
214 VLOG(1) << "NFC tag found: " << object_path
.value();
216 // Check to see if the tag belongs to this adapter.
217 const std::vector
<dbus::ObjectPath
>& tags
=
218 DBusThreadManager::Get()->GetNfcTagClient()->
219 GetTagsForAdapter(object_path_
);
220 bool tag_found
= false;
221 for (std::vector
<dbus::ObjectPath
>::const_iterator iter
= tags
.begin();
222 iter
!= tags
.end(); ++iter
) {
223 if (*iter
== object_path
) {
229 VLOG(1) << "Found tag does not belong to the current adapter.";
233 // Create the tag object.
234 NfcTagChromeOS
* tag_chromeos
= new NfcTagChromeOS(object_path
);
235 SetTag(object_path
.value(), tag_chromeos
);
236 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
237 TagFound(this, tag_chromeos
));
240 void NfcAdapterChromeOS::TagRemoved(const dbus::ObjectPath
& object_path
) {
241 VLOG(1) << "NFC tag lost : " << object_path
.value();
242 device::NfcTag
* tag
= RemoveTag(object_path
.value());
244 VLOG(1) << "Removed tag does not belong to the current adapter.";
247 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
, TagLost(this, tag
));
251 void NfcAdapterChromeOS::SetAdapter(const dbus::ObjectPath
& object_path
) {
252 DCHECK(!IsPresent());
253 object_path_
= object_path
;
254 VLOG(1) << "Using NFC adapter: " << object_path
.value();
256 NfcAdapterClient::Properties
* properties
=
257 DBusThreadManager::Get()->GetNfcAdapterClient()->
258 GetProperties(object_path_
);
259 PresentChanged(true);
260 if (properties
->powered
.value())
261 PoweredChanged(true);
262 if (properties
->polling
.value())
263 PollingChanged(true);
265 // Create peer objects for peers that were added before the adapter was set.
266 const ObjectPathVector
& devices
=
267 DBusThreadManager::Get()->GetNfcDeviceClient()->
268 GetDevicesForAdapter(object_path_
);
269 for (ObjectPathVector::const_iterator iter
= devices
.begin();
270 iter
!= devices
.end(); ++iter
) {
271 const dbus::ObjectPath
& object_path
= *iter
;
272 if (GetPeer(object_path
.value()))
274 NfcPeerChromeOS
* peer_chromeos
= new NfcPeerChromeOS(object_path
);
275 SetPeer(object_path
.value(), peer_chromeos
);
276 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
277 PeerFound(this, peer_chromeos
));
280 // Create tag objects for tags that were added before the adapter was set.
281 const std::vector
<dbus::ObjectPath
>& tags
=
282 DBusThreadManager::Get()->GetNfcTagClient()->
283 GetTagsForAdapter(object_path_
);
284 for (std::vector
<dbus::ObjectPath
>::const_iterator iter
= tags
.begin();
285 iter
!= tags
.end(); ++iter
) {
286 const dbus::ObjectPath
& object_path
= *iter
;
287 if (GetTag(object_path
.value()))
289 NfcTagChromeOS
* tag_chromeos
= new NfcTagChromeOS(object_path
);
290 SetTag(object_path
.value(), tag_chromeos
);
291 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
292 TagFound(this, tag_chromeos
));
296 void NfcAdapterChromeOS::RemoveAdapter() {
298 VLOG(1) << "NFC adapter removed: " << object_path_
.value();
300 NfcAdapterClient::Properties
* properties
=
301 DBusThreadManager::Get()->GetNfcAdapterClient()->
302 GetProperties(object_path_
);
303 if (properties
->powered
.value())
304 PoweredChanged(false);
305 if (properties
->polling
.value())
306 PollingChanged(false);
308 // Copy the tags and peers here and clear the original containers so that
309 // GetPeers and GetTags return no values during the *Removed observer calls.
317 for (PeerList::iterator iter
= peers
.begin();
318 iter
!= peers
.end(); ++iter
) {
319 device::NfcPeer
* peer
= *iter
;
320 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
321 PeerLost(this, peer
));
324 for (TagList::iterator iter
= tags
.begin();
325 iter
!= tags
.end(); ++iter
) {
326 device::NfcTag
* tag
= *iter
;
327 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
332 object_path_
= dbus::ObjectPath("");
333 PresentChanged(false);
336 void NfcAdapterChromeOS::PoweredChanged(bool powered
) {
337 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
338 AdapterPoweredChanged(this, powered
));
341 void NfcAdapterChromeOS::PollingChanged(bool polling
) {
342 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
343 AdapterPollingChanged(this, polling
));
346 void NfcAdapterChromeOS::PresentChanged(bool present
) {
347 FOR_EACH_OBSERVER(NfcAdapter::Observer
, observers_
,
348 AdapterPresentChanged(this, present
));
351 void NfcAdapterChromeOS::OnSetPowered(const base::Closure
& callback
,
352 const ErrorCallback
& error_callback
,
354 VLOG(1) << "NfcAdapterChromeOS::OnSetPowered result: " << success
;
356 // TODO(armansito): There is a bug in neard 0.13 that causes it not to emit
357 // a signal when the "Powered" property changes. Sync the properties here,
358 // but remove it in neard 0.14.
360 DBusThreadManager::Get()->GetNfcAdapterClient()->
361 GetProperties(object_path_
)->GetAll();
365 LOG(ERROR
) << "Failed to power up the NFC antenna radio.";
366 error_callback
.Run();
370 void NfcAdapterChromeOS::OnStartPolling(const base::Closure
& callback
) {
374 void NfcAdapterChromeOS::OnStartPollingError(
375 const ErrorCallback
& error_callback
,
376 const std::string
& error_name
,
377 const std::string
& error_message
) {
378 LOG(ERROR
) << object_path_
.value() << ": Failed to start polling: "
379 << error_name
<< ": " << error_message
;
380 error_callback
.Run();
383 void NfcAdapterChromeOS::OnStopPolling(const base::Closure
& callback
) {
387 void NfcAdapterChromeOS::OnStopPollingError(
388 const ErrorCallback
& error_callback
,
389 const std::string
& error_name
,
390 const std::string
& error_message
) {
391 LOG(ERROR
) << object_path_
.value() << ": Failed to stop polling: "
392 << error_name
<< ": " << error_message
;
393 error_callback
.Run();
396 } // namespace chromeos