15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/nfc/nfc_tag_chromeos.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "device/nfc/nfc_tag_technology_chromeos.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using device::NfcTag;
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using device::NfcTagTechnology;
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using device::NfcNdefTagTechnology;
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace chromeos {
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Converts an NFC tag type value returned by neard to a NfcTag::TagType enum
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// value.
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTag::TagType DBusTypePropertyToTagType(const std::string& type) {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == nfc_tag::kTagType1)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kTagType1;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == nfc_tag::kTagType2)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kTagType2;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == nfc_tag::kTagType3)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kTagType3;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == nfc_tag::kTagType4)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kTagType4;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NfcTag::kTagTypeUnknown;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Converts an NFC tag protocol value returned by neard to a NfcTag::Protocol
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// enum value.
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTag::Protocol DBusProtocolPropertyToTagProtocol(
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& protocol) {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (protocol == nfc_common::kProtocolFelica)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kProtocolFelica;
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (protocol == nfc_common::kProtocolIsoDep)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kProtocolIsoDep;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (protocol == nfc_common::kProtocolJewel)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kProtocolJewel;
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (protocol == nfc_common::kProtocolMifare)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kProtocolMifare;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (protocol == nfc_common::kProtocolNfcDep)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NfcTag::kProtocolNfcDep;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NfcTag::kProtocolUnknown;
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTagChromeOS::NfcTagChromeOS(const dbus::ObjectPath& object_path)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : object_path_(object_path),
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_ready_(false),
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ndef_technology_(new NfcNdefTagTechnologyChromeOS(this)) {
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this);
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTagChromeOS::~NfcTagChromeOS() {
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this);
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NfcTagChromeOS::AddObserver(NfcTag::Observer* observer) {
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observers_.AddObserver(observer);
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NfcTagChromeOS::RemoveObserver(NfcTag::Observer* observer) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observers_.RemoveObserver(observer);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string NfcTagChromeOS::GetIdentifier() const {
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return object_path_.value();
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTag::TagType NfcTagChromeOS::GetType() const {
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(object_path_.IsValid());
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return DBusTypePropertyToTagType(
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DBusThreadManager::Get()->GetNfcTagClient()->
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          GetProperties(object_path_)->type.value());
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NfcTagChromeOS::IsReadOnly() const {
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(object_path_.IsValid());
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return DBusThreadManager::Get()->GetNfcTagClient()->
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetProperties(object_path_)->read_only.value();
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTag::Protocol NfcTagChromeOS::GetSupportedProtocol() const {
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(object_path_.IsValid());
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return DBusProtocolPropertyToTagProtocol(
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DBusThreadManager::Get()->GetNfcTagClient()->
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          GetProperties(object_path_)->protocol.value());
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTagTechnology::TechnologyTypeMask
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcTagChromeOS::GetSupportedTechnologies() const {
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Determine supported technologies based on the tag's protocol and
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // type.
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NfcTag::TagType type = GetType();
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NfcTag::Protocol protocol = GetSupportedProtocol();
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == NfcTag::kTagTypeUnknown || protocol == kProtocolUnknown) {
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VLOG(1) << "Tag type and protocol unknown.";
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NfcTagTechnology::TechnologyTypeMask technologies = 0;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  technologies |= NfcTagTechnology::kTechnologyTypeNdef;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (type == NfcTag::kTagType3) {
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(protocol == NfcTag::kProtocolFelica);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return technologies | NfcTagTechnology::kTechnologyTypeNfcF;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (protocol == NfcTag::kProtocolIsoDep) {
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(type == NfcTag::kTagType4);
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    technologies |= NfcTagTechnology::kTechnologyTypeIsoDep;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(armansito): Neard doesn't provide enough information to determine
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // if the underlying wave-form is type A or type B. For now, report
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // neither.
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return technologies;
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return technologies | NfcTagTechnology::kTechnologyTypeNfcA;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NfcTagChromeOS::IsReady() const {
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return is_ready_;
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NfcNdefTagTechnology* NfcTagChromeOS::GetNdefTagTechnology() {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ndef_technology_.get();
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NfcTagChromeOS::TagPropertyChanged(const dbus::ObjectPath& object_path,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const std::string& property_name) {
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (object_path != object_path_)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NfcTagClient::Properties* properties =
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DBusThreadManager::Get()->GetNfcTagClient()->GetProperties(object_path_);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(properties);
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (property_name == properties->type.name()) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(NfcTag::Observer, observers_,
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      TagTypeChanged(this, GetType()));
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (property_name == properties->read_only.name()) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(NfcTag::Observer, observers_,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      TagWritePermissionChanged(this, IsReadOnly()));
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (property_name == properties->protocol.name()) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FOR_EACH_OBSERVER(
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        NfcTag::Observer, observers_,
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        TagSupportedProtocolChanged(this, GetSupportedProtocol()));
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NfcTagChromeOS::TagPropertiesReceived(
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const dbus::ObjectPath& object_path) {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_ready_ || object_path != object_path_)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  is_ready_ = true;
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(NfcTag::Observer, observers_, TagReady(this));
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace chromeos
165