Atmosphere/libraries/libstratosphere/include/stratosphere/settings/settings_types.hpp
ndeadly bd9d8fff46
Add system setting to mirror bluetooth pairing database to sd card (#1787)
* ams_mitm: add ability to mirror bluetooth device pairing database to sd card via a system setting

* ams_mitm: address requested stylistic changes

* ams_mitm: make use of R_SUCCEED macro

* ams_mitm: use settings::BluetoothDevicesSettings instead of libnx type

* ams_mitm: fix logic error when truncating pairing database on read

* Update .ini comment

* ams_mitm: missing R_TRY around call to fs::FlushFile

* stratosphere: remove union from BluetoothDevicesSettings type

---------

Co-authored-by: ndeadly <24677491+ndeadly@users.noreply.github.com>
2023-03-10 10:06:38 -07:00

264 lines
9.1 KiB
C++

/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::settings {
constexpr size_t SettingsNameLengthMax = 0x40;
constexpr size_t SettingsItemKeyLengthMax = 0x40;
struct SettingsName : public sf::LargeData {
char value[util::AlignUp(SettingsNameLengthMax + 1, alignof(u64))];
};
static_assert(util::is_pod<SettingsName>::value && sizeof(SettingsName) > SettingsNameLengthMax);
struct SettingsItemKey : public sf::LargeData {
char value[util::AlignUp(SettingsItemKeyLengthMax + 1, alignof(u64))];
};
static_assert(util::is_pod<SettingsItemKey>::value && sizeof(SettingsItemKey) > SettingsItemKeyLengthMax);
enum Language {
Language_Japanese,
Language_AmericanEnglish,
Language_French,
Language_German,
Language_Italian,
Language_Spanish,
Language_Chinese,
Language_Korean,
Language_Dutch,
Language_Portuguese,
Language_Russian,
Language_Taiwanese,
Language_BritishEnglish,
Language_CanadianFrench,
Language_LatinAmericanSpanish,
/* 4.0.0+ */
Language_SimplifiedChinese,
Language_TraditionalChinese,
Language_Count,
};
struct LanguageCode {
static constexpr size_t MaxLength = 8;
char name[MaxLength];
static constexpr LanguageCode Encode(util::string_view name) {
LanguageCode out{};
for (size_t i = 0; i < MaxLength && i < name.size(); i++) {
out.name[i] = name[i];
}
return out;
}
template<Language Lang>
static constexpr inline LanguageCode EncodeLanguage() {
if constexpr (false) { /* ... */ }
#define AMS_MATCH_LANGUAGE(lang, enc) else if constexpr (Lang == Language_##lang) { return LanguageCode::Encode(enc); }
AMS_MATCH_LANGUAGE(Japanese, "ja")
AMS_MATCH_LANGUAGE(AmericanEnglish, "en-US")
AMS_MATCH_LANGUAGE(French, "fr")
AMS_MATCH_LANGUAGE(German, "de")
AMS_MATCH_LANGUAGE(Italian, "it")
AMS_MATCH_LANGUAGE(Spanish, "es")
AMS_MATCH_LANGUAGE(Chinese, "zh-CN")
AMS_MATCH_LANGUAGE(Korean, "ko")
AMS_MATCH_LANGUAGE(Dutch, "nl")
AMS_MATCH_LANGUAGE(Portuguese, "pt")
AMS_MATCH_LANGUAGE(Russian, "ru")
AMS_MATCH_LANGUAGE(Taiwanese, "zh-TW")
AMS_MATCH_LANGUAGE(BritishEnglish, "en-GB")
AMS_MATCH_LANGUAGE(CanadianFrench, "fr-CA")
AMS_MATCH_LANGUAGE(LatinAmericanSpanish, "es-419")
/* 4.0.0+ */
AMS_MATCH_LANGUAGE(SimplifiedChinese, "zh-Hans")
AMS_MATCH_LANGUAGE(TraditionalChinese, "zh-Hant")
#undef AMS_MATCH_LANGUAGE
else { static_assert(Lang != Language_Japanese); }
}
static constexpr inline LanguageCode Encode(const Language language) {
constexpr LanguageCode EncodedLanguages[Language_Count] = {
EncodeLanguage<Language_Japanese>(),
EncodeLanguage<Language_AmericanEnglish>(),
EncodeLanguage<Language_French>(),
EncodeLanguage<Language_German>(),
EncodeLanguage<Language_Italian>(),
EncodeLanguage<Language_Spanish>(),
EncodeLanguage<Language_Chinese>(),
EncodeLanguage<Language_Korean>(),
EncodeLanguage<Language_Dutch>(),
EncodeLanguage<Language_Portuguese>(),
EncodeLanguage<Language_Russian>(),
EncodeLanguage<Language_Taiwanese>(),
EncodeLanguage<Language_BritishEnglish>(),
EncodeLanguage<Language_CanadianFrench>(),
EncodeLanguage<Language_LatinAmericanSpanish>(),
/* 4.0.0+ */
EncodeLanguage<Language_SimplifiedChinese>(),
EncodeLanguage<Language_TraditionalChinese>(),
};
return EncodedLanguages[language];
}
};
constexpr inline bool operator==(const LanguageCode &lhs, const LanguageCode &rhs) {
return util::Strncmp<char>(lhs.name, rhs.name, sizeof(lhs)) == 0;
}
constexpr inline bool operator!=(const LanguageCode &lhs, const LanguageCode &rhs) {
return !(lhs == rhs);
}
constexpr inline bool operator==(const LanguageCode &lhs, const Language &rhs) {
return lhs == LanguageCode::Encode(rhs);
}
constexpr inline bool operator!=(const LanguageCode &lhs, const Language &rhs) {
return !(lhs == rhs);
}
constexpr inline bool operator==(const Language &lhs, const LanguageCode &rhs) {
return rhs == lhs;
}
constexpr inline bool operator!=(const Language &lhs, const LanguageCode &rhs) {
return !(lhs == rhs);
}
namespace impl {
template<size_t ...Is>
constexpr inline bool IsValidLanguageCode(const LanguageCode &lc, std::index_sequence<Is...>) {
return ((lc == LanguageCode::Encode(static_cast<Language>(Is))) || ...);
}
}
constexpr inline bool IsValidLanguageCodeDeprecated(const LanguageCode &lc) {
return impl::IsValidLanguageCode(lc, std::make_index_sequence<Language_Count - 2>{});
}
constexpr inline bool IsValidLanguageCode(const LanguageCode &lc) {
return impl::IsValidLanguageCode(lc, std::make_index_sequence<Language_Count>{});
}
static_assert(util::is_pod<LanguageCode>::value);
static_assert(sizeof(LanguageCode) == sizeof(u64));
/* Not an official type, but convenient. */
enum RegionCode : s32 {
RegionCode_Japan,
RegionCode_America,
RegionCode_Europe,
RegionCode_Australia,
RegionCode_China,
RegionCode_Korea,
RegionCode_Taiwan,
RegionCode_Count,
};
constexpr inline bool IsValidRegionCode(const RegionCode rc) {
return 0 <= rc && rc < RegionCode_Count;
}
/* This needs to be defined separately from libnx's so that it can inherit from sf::LargeData. */
struct FirmwareVersion : public sf::LargeData {
u8 major;
u8 minor;
u8 micro;
u8 padding1;
u8 revision_major;
u8 revision_minor;
u8 padding2;
u8 padding3;
char platform[0x20];
char version_hash[0x40];
char display_version[0x18];
char display_title[0x80];
constexpr inline u32 GetVersion() const {
return (static_cast<u32>(major) << 16) | (static_cast<u32>(minor) << 8) | (static_cast<u32>(micro) << 0);
}
};
static_assert(util::is_pod<FirmwareVersion>::value);
static_assert(sizeof(FirmwareVersion) == 0x100);
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(FirmwareVersion) == sizeof(::SetSysFirmwareVersion));
#endif
constexpr inline bool operator==(const FirmwareVersion &lhs, const FirmwareVersion &rhs) {
return lhs.GetVersion() == rhs.GetVersion();
}
constexpr inline bool operator!=(const FirmwareVersion &lhs, const FirmwareVersion &rhs) {
return !(lhs == rhs);
}
constexpr inline bool operator<(const FirmwareVersion &lhs, const FirmwareVersion &rhs) {
return lhs.GetVersion() < rhs.GetVersion();
}
constexpr inline bool operator>=(const FirmwareVersion &lhs, const FirmwareVersion &rhs) {
return !(lhs < rhs);
}
constexpr inline bool operator<=(const FirmwareVersion &lhs, const FirmwareVersion &rhs) {
return lhs.GetVersion() <= rhs.GetVersion();
}
constexpr inline bool operator>(const FirmwareVersion &lhs, const FirmwareVersion &rhs) {
return !(lhs <= rhs);
}
struct BluetoothDevicesSettings : public sf::LargeData {
u8 address[0x6];
char name[0x20];
u8 class_of_device[0x3];
u8 link_key[0x10];
u8 link_key_present;
u16 version;
u32 trusted_services;
u16 vid;
u16 pid;
u8 sub_class;
u8 attribute_mask;
u16 descriptor_length;
u8 descriptor[0x80];
u8 key_type;
u8 device_type;
u16 brr_size;
u8 brr[0x9];
u8 reserved0;
char name2[0xF9];
u8 reserved1[0x31];
};
static_assert(sizeof(BluetoothDevicesSettings) == sizeof(::SetSysBluetoothDevicesSettings));
}