1 // Copyright 2014 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_tag_chromeos.h"
6
7 #include "chromeos/dbus/dbus_thread_manager.h"
8 #include "device/nfc/nfc_tag_technology_chromeos.h"
9 #include "third_party/cros_system_api/dbus/service_constants.h"
10
11 using device::NfcTag;
12 using device::NfcTagTechnology;
13 using device::NfcNdefTagTechnology;
14
15 namespace chromeos {
16
17 namespace {
18
19 // Converts an NFC tag type value returned by neard to a NfcTag::TagType enum
20 // value.
DBusTypePropertyToTagType(const std::string & type)21 NfcTag::TagType DBusTypePropertyToTagType(const std::string& type) {
22 if (type == nfc_tag::kTagType1)
23 return NfcTag::kTagType1;
24 if (type == nfc_tag::kTagType2)
25 return NfcTag::kTagType2;
26 if (type == nfc_tag::kTagType3)
27 return NfcTag::kTagType3;
28 if (type == nfc_tag::kTagType4)
29 return NfcTag::kTagType4;
30 return NfcTag::kTagTypeUnknown;
31 }
32
33 // Converts an NFC tag protocol value returned by neard to a NfcTag::Protocol
34 // enum value.
DBusProtocolPropertyToTagProtocol(const std::string & protocol)35 NfcTag::Protocol DBusProtocolPropertyToTagProtocol(
36 const std::string& protocol) {
37 if (protocol == nfc_common::kProtocolFelica)
38 return NfcTag::kProtocolFelica;
39 if (protocol == nfc_common::kProtocolIsoDep)
40 return NfcTag::kProtocolIsoDep;
41 if (protocol == nfc_common::kProtocolJewel)
42 return NfcTag::kProtocolJewel;
43 if (protocol == nfc_common::kProtocolMifare)
44 return NfcTag::kProtocolMifare;
45 if (protocol == nfc_common::kProtocolNfcDep)
46 return NfcTag::kProtocolNfcDep;
47 return NfcTag::kProtocolUnknown;
48 }
49
50 } // namespace
51
NfcTagChromeOS(const dbus::ObjectPath & object_path)52 NfcTagChromeOS::NfcTagChromeOS(const dbus::ObjectPath& object_path)
53 : object_path_(object_path),
54 is_ready_(false),
55 ndef_technology_(new NfcNdefTagTechnologyChromeOS(this)) {
56 DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this);
57 }
58
~NfcTagChromeOS()59 NfcTagChromeOS::~NfcTagChromeOS() {
60 DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this);
61 }
62
AddObserver(NfcTag::Observer * observer)63 void NfcTagChromeOS::AddObserver(NfcTag::Observer* observer) {
64 observers_.AddObserver(observer);
65 }
66
RemoveObserver(NfcTag::Observer * observer)67 void NfcTagChromeOS::RemoveObserver(NfcTag::Observer* observer) {
68 observers_.RemoveObserver(observer);
69 }
70
GetIdentifier() const71 std::string NfcTagChromeOS::GetIdentifier() const {
72 return object_path_.value();
73 }
74
GetType() const75 NfcTag::TagType NfcTagChromeOS::GetType() const {
76 DCHECK(object_path_.IsValid());
77 return DBusTypePropertyToTagType(
78 DBusThreadManager::Get()->GetNfcTagClient()->
79 GetProperties(object_path_)->type.value());
80 }
81
IsReadOnly() const82 bool NfcTagChromeOS::IsReadOnly() const {
83 DCHECK(object_path_.IsValid());
84 return DBusThreadManager::Get()->GetNfcTagClient()->
85 GetProperties(object_path_)->read_only.value();
86 }
87
GetSupportedProtocol() const88 NfcTag::Protocol NfcTagChromeOS::GetSupportedProtocol() const {
89 DCHECK(object_path_.IsValid());
90 return DBusProtocolPropertyToTagProtocol(
91 DBusThreadManager::Get()->GetNfcTagClient()->
92 GetProperties(object_path_)->protocol.value());
93 }
94
95 NfcTagTechnology::TechnologyTypeMask
GetSupportedTechnologies() const96 NfcTagChromeOS::GetSupportedTechnologies() const {
97 // Determine supported technologies based on the tag's protocol and
98 // type.
99 NfcTag::TagType type = GetType();
100 NfcTag::Protocol protocol = GetSupportedProtocol();
101 if (type == NfcTag::kTagTypeUnknown || protocol == kProtocolUnknown) {
102 VLOG(1) << "Tag type and protocol unknown.";
103 return 0;
104 }
105
106 NfcTagTechnology::TechnologyTypeMask technologies = 0;
107 technologies |= NfcTagTechnology::kTechnologyTypeNdef;
108 if (type == NfcTag::kTagType3) {
109 DCHECK(protocol == NfcTag::kProtocolFelica);
110 return technologies | NfcTagTechnology::kTechnologyTypeNfcF;
111 }
112
113 if (protocol == NfcTag::kProtocolIsoDep) {
114 DCHECK(type == NfcTag::kTagType4);
115 technologies |= NfcTagTechnology::kTechnologyTypeIsoDep;
116 // TODO(armansito): Neard doesn't provide enough information to determine
117 // if the underlying wave-form is type A or type B. For now, report
118 // neither.
119 return technologies;
120 }
121
122 return technologies | NfcTagTechnology::kTechnologyTypeNfcA;
123 }
124
IsReady() const125 bool NfcTagChromeOS::IsReady() const {
126 return is_ready_;
127 }
128
GetNdefTagTechnology()129 NfcNdefTagTechnology* NfcTagChromeOS::GetNdefTagTechnology() {
130 return ndef_technology_.get();
131 }
132
TagPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)133 void NfcTagChromeOS::TagPropertyChanged(const dbus::ObjectPath& object_path,
134 const std::string& property_name) {
135 if (object_path != object_path_)
136 return;
137
138 NfcTagClient::Properties* properties =
139 DBusThreadManager::Get()->GetNfcTagClient()->GetProperties(object_path_);
140 DCHECK(properties);
141
142 if (property_name == properties->type.name()) {
143 FOR_EACH_OBSERVER(NfcTag::Observer, observers_,
144 TagTypeChanged(this, GetType()));
145 } else if (property_name == properties->read_only.name()) {
146 FOR_EACH_OBSERVER(NfcTag::Observer, observers_,
147 TagWritePermissionChanged(this, IsReadOnly()));
148 } else if (property_name == properties->protocol.name()) {
149 FOR_EACH_OBSERVER(
150 NfcTag::Observer, observers_,
151 TagSupportedProtocolChanged(this, GetSupportedProtocol()));
152 }
153 }
154
TagPropertiesReceived(const dbus::ObjectPath & object_path)155 void NfcTagChromeOS::TagPropertiesReceived(
156 const dbus::ObjectPath& object_path) {
157 if (is_ready_ || object_path != object_path_)
158 return;
159
160 is_ready_ = true;
161 FOR_EACH_OBSERVER(NfcTag::Observer, observers_, TagReady(this));
162 }
163
164 } // namespace chromeos
165