diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nfp/nfp.cpp | 454 | ||||
| -rw-r--r-- | src/core/hle/service/nfp/nfp.h | 102 |
2 files changed, 299 insertions, 257 deletions
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index e8d3a6b53..cedade5c2 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp | |||
| @@ -17,315 +17,255 @@ namespace ErrCodes { | |||
| 17 | constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); | 17 | constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); |
| 18 | } // namespace ErrCodes | 18 | } // namespace ErrCodes |
| 19 | 19 | ||
| 20 | Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, | 20 | IUser::IUser(Module::Interface& nfp_interface_, Core::System& system_) |
| 21 | const char* name) | 21 | : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_}, |
| 22 | : ServiceFramework{system_, name}, module{std::move(module_)}, service_context{system_, | 22 | deactivate_event{system.Kernel()}, availability_change_event{system.Kernel()} { |
| 23 | "NFP::IUser"} { | 23 | static const FunctionInfo functions[] = { |
| 24 | nfc_tag_load = service_context.CreateEvent("NFP::IUser:NFCTagDetected"); | 24 | {0, &IUser::Initialize, "Initialize"}, |
| 25 | } | 25 | {1, &IUser::Finalize, "Finalize"}, |
| 26 | {2, &IUser::ListDevices, "ListDevices"}, | ||
| 27 | {3, &IUser::StartDetection, "StartDetection"}, | ||
| 28 | {4, &IUser::StopDetection, "StopDetection"}, | ||
| 29 | {5, &IUser::Mount, "Mount"}, | ||
| 30 | {6, &IUser::Unmount, "Unmount"}, | ||
| 31 | {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, | ||
| 32 | {8, &IUser::GetApplicationArea, "GetApplicationArea"}, | ||
| 33 | {9, nullptr, "SetApplicationArea"}, | ||
| 34 | {10, nullptr, "Flush"}, | ||
| 35 | {11, nullptr, "Restore"}, | ||
| 36 | {12, nullptr, "CreateApplicationArea"}, | ||
| 37 | {13, &IUser::GetTagInfo, "GetTagInfo"}, | ||
| 38 | {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, | ||
| 39 | {15, &IUser::GetCommonInfo, "GetCommonInfo"}, | ||
| 40 | {16, &IUser::GetModelInfo, "GetModelInfo"}, | ||
| 41 | {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, | ||
| 42 | {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, | ||
| 43 | {19, &IUser::GetState, "GetState"}, | ||
| 44 | {20, &IUser::GetDeviceState, "GetDeviceState"}, | ||
| 45 | {21, &IUser::GetNpadId, "GetNpadId"}, | ||
| 46 | {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, | ||
| 47 | {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, | ||
| 48 | {24, nullptr, "RecreateApplicationArea"}, | ||
| 49 | }; | ||
| 50 | RegisterHandlers(functions); | ||
| 26 | 51 | ||
| 27 | Module::Interface::~Interface() { | 52 | Kernel::KAutoObject::Create(std::addressof(deactivate_event)); |
| 28 | service_context.CloseEvent(nfc_tag_load); | 53 | Kernel::KAutoObject::Create(std::addressof(availability_change_event)); |
| 29 | } | ||
| 30 | 54 | ||
| 31 | class IUser final : public ServiceFramework<IUser> { | 55 | deactivate_event.Initialize("IUser:DeactivateEvent"); |
| 32 | public: | 56 | availability_change_event.Initialize("IUser:AvailabilityChangeEvent"); |
| 33 | explicit IUser(Module::Interface& nfp_interface_, Core::System& system_, | 57 | } |
| 34 | KernelHelpers::ServiceContext& service_context_) | ||
| 35 | : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_}, | ||
| 36 | service_context{service_context_} { | ||
| 37 | static const FunctionInfo functions[] = { | ||
| 38 | {0, &IUser::Initialize, "Initialize"}, | ||
| 39 | {1, &IUser::Finalize, "Finalize"}, | ||
| 40 | {2, &IUser::ListDevices, "ListDevices"}, | ||
| 41 | {3, &IUser::StartDetection, "StartDetection"}, | ||
| 42 | {4, &IUser::StopDetection, "StopDetection"}, | ||
| 43 | {5, &IUser::Mount, "Mount"}, | ||
| 44 | {6, &IUser::Unmount, "Unmount"}, | ||
| 45 | {7, &IUser::OpenApplicationArea, "OpenApplicationArea"}, | ||
| 46 | {8, &IUser::GetApplicationArea, "GetApplicationArea"}, | ||
| 47 | {9, nullptr, "SetApplicationArea"}, | ||
| 48 | {10, nullptr, "Flush"}, | ||
| 49 | {11, nullptr, "Restore"}, | ||
| 50 | {12, nullptr, "CreateApplicationArea"}, | ||
| 51 | {13, &IUser::GetTagInfo, "GetTagInfo"}, | ||
| 52 | {14, &IUser::GetRegisterInfo, "GetRegisterInfo"}, | ||
| 53 | {15, &IUser::GetCommonInfo, "GetCommonInfo"}, | ||
| 54 | {16, &IUser::GetModelInfo, "GetModelInfo"}, | ||
| 55 | {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, | ||
| 56 | {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, | ||
| 57 | {19, &IUser::GetState, "GetState"}, | ||
| 58 | {20, &IUser::GetDeviceState, "GetDeviceState"}, | ||
| 59 | {21, &IUser::GetNpadId, "GetNpadId"}, | ||
| 60 | {22, &IUser::GetApplicationAreaSize, "GetApplicationAreaSize"}, | ||
| 61 | {23, &IUser::AttachAvailabilityChangeEvent, "AttachAvailabilityChangeEvent"}, | ||
| 62 | {24, nullptr, "RecreateApplicationArea"}, | ||
| 63 | }; | ||
| 64 | RegisterHandlers(functions); | ||
| 65 | |||
| 66 | deactivate_event = service_context.CreateEvent("NFP::IUser:DeactivateEvent"); | ||
| 67 | availability_change_event = | ||
| 68 | service_context.CreateEvent("NFP::IUser:AvailabilityChangeEvent"); | ||
| 69 | } | ||
| 70 | 58 | ||
| 71 | ~IUser() override { | 59 | void IUser::Initialize(Kernel::HLERequestContext& ctx) { |
| 72 | service_context.CloseEvent(deactivate_event); | 60 | LOG_DEBUG(Service_NFC, "called"); |
| 73 | service_context.CloseEvent(availability_change_event); | ||
| 74 | } | ||
| 75 | 61 | ||
| 76 | private: | 62 | IPC::ResponseBuilder rb{ctx, 2, 0}; |
| 77 | struct TagInfo { | 63 | rb.Push(ResultSuccess); |
| 78 | std::array<u8, 10> uuid; | ||
| 79 | u8 uuid_length; // TODO(ogniK): Figure out if this is actual the uuid length or does it | ||
| 80 | // mean something else | ||
| 81 | std::array<u8, 0x15> padding_1; | ||
| 82 | u32_le protocol; | ||
| 83 | u32_le tag_type; | ||
| 84 | std::array<u8, 0x2c> padding_2; | ||
| 85 | }; | ||
| 86 | static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size"); | ||
| 87 | 64 | ||
| 88 | enum class State : u32 { | 65 | state = State::Initialized; |
| 89 | NonInitialized = 0, | 66 | } |
| 90 | Initialized = 1, | ||
| 91 | }; | ||
| 92 | 67 | ||
| 93 | enum class DeviceState : u32 { | 68 | void IUser::Finalize(Kernel::HLERequestContext& ctx) { |
| 94 | Initialized = 0, | 69 | LOG_DEBUG(Service_NFP, "called"); |
| 95 | SearchingForTag = 1, | ||
| 96 | TagFound = 2, | ||
| 97 | TagRemoved = 3, | ||
| 98 | TagNearby = 4, | ||
| 99 | Unknown5 = 5, | ||
| 100 | Finalized = 6 | ||
| 101 | }; | ||
| 102 | 70 | ||
| 103 | struct CommonInfo { | 71 | device_state = DeviceState::Finalized; |
| 104 | u16_be last_write_year; | ||
| 105 | u8 last_write_month; | ||
| 106 | u8 last_write_day; | ||
| 107 | u16_be write_counter; | ||
| 108 | u16_be version; | ||
| 109 | u32_be application_area_size; | ||
| 110 | INSERT_PADDING_BYTES(0x34); | ||
| 111 | }; | ||
| 112 | static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size"); | ||
| 113 | 72 | ||
| 114 | void Initialize(Kernel::HLERequestContext& ctx) { | 73 | IPC::ResponseBuilder rb{ctx, 2}; |
| 115 | LOG_DEBUG(Service_NFC, "called"); | 74 | rb.Push(ResultSuccess); |
| 75 | } | ||
| 116 | 76 | ||
| 117 | IPC::ResponseBuilder rb{ctx, 2, 0}; | 77 | void IUser::ListDevices(Kernel::HLERequestContext& ctx) { |
| 118 | rb.Push(ResultSuccess); | 78 | IPC::RequestParser rp{ctx}; |
| 79 | const u32 array_size = rp.Pop<u32>(); | ||
| 80 | LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); | ||
| 119 | 81 | ||
| 120 | state = State::Initialized; | 82 | ctx.WriteBuffer(device_handle); |
| 121 | } | ||
| 122 | 83 | ||
| 123 | void Finalize(Kernel::HLERequestContext& ctx) { | 84 | IPC::ResponseBuilder rb{ctx, 3}; |
| 124 | LOG_DEBUG(Service_NFP, "called"); | 85 | rb.Push(ResultSuccess); |
| 86 | rb.Push<u32>(1); | ||
| 87 | } | ||
| 125 | 88 | ||
| 126 | device_state = DeviceState::Finalized; | 89 | void IUser::StartDetection(Kernel::HLERequestContext& ctx) { |
| 90 | LOG_DEBUG(Service_NFP, "called"); | ||
| 127 | 91 | ||
| 128 | IPC::ResponseBuilder rb{ctx, 2}; | 92 | if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { |
| 129 | rb.Push(ResultSuccess); | 93 | device_state = DeviceState::SearchingForTag; |
| 130 | } | 94 | } |
| 95 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 96 | rb.Push(ResultSuccess); | ||
| 97 | } | ||
| 131 | 98 | ||
| 132 | void ListDevices(Kernel::HLERequestContext& ctx) { | 99 | void IUser::StopDetection(Kernel::HLERequestContext& ctx) { |
| 133 | IPC::RequestParser rp{ctx}; | 100 | LOG_DEBUG(Service_NFP, "called"); |
| 134 | const u32 array_size = rp.Pop<u32>(); | ||
| 135 | LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); | ||
| 136 | |||
| 137 | ctx.WriteBuffer(device_handle); | ||
| 138 | 101 | ||
| 139 | IPC::ResponseBuilder rb{ctx, 3}; | 102 | switch (device_state) { |
| 140 | rb.Push(ResultSuccess); | 103 | case DeviceState::TagFound: |
| 141 | rb.Push<u32>(1); | 104 | case DeviceState::TagMounted: |
| 105 | deactivate_event.GetWritableEvent().Signal(); | ||
| 106 | device_state = DeviceState::Initialized; | ||
| 107 | break; | ||
| 108 | case DeviceState::SearchingForTag: | ||
| 109 | case DeviceState::TagRemoved: | ||
| 110 | device_state = DeviceState::Initialized; | ||
| 111 | break; | ||
| 112 | default: | ||
| 113 | break; | ||
| 142 | } | 114 | } |
| 115 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 116 | rb.Push(ResultSuccess); | ||
| 117 | } | ||
| 143 | 118 | ||
| 144 | void StartDetection(Kernel::HLERequestContext& ctx) { | 119 | void IUser::Mount(Kernel::HLERequestContext& ctx) { |
| 145 | LOG_DEBUG(Service_NFP, "called"); | 120 | LOG_DEBUG(Service_NFP, "called"); |
| 146 | |||
| 147 | if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { | ||
| 148 | device_state = DeviceState::SearchingForTag; | ||
| 149 | } | ||
| 150 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 151 | rb.Push(ResultSuccess); | ||
| 152 | } | ||
| 153 | 121 | ||
| 154 | void StopDetection(Kernel::HLERequestContext& ctx) { | 122 | device_state = DeviceState::TagMounted; |
| 155 | LOG_DEBUG(Service_NFP, "called"); | 123 | IPC::ResponseBuilder rb{ctx, 2}; |
| 156 | 124 | rb.Push(ResultSuccess); | |
| 157 | switch (device_state) { | 125 | } |
| 158 | case DeviceState::TagFound: | ||
| 159 | case DeviceState::TagNearby: | ||
| 160 | deactivate_event->GetWritableEvent().Signal(); | ||
| 161 | device_state = DeviceState::Initialized; | ||
| 162 | break; | ||
| 163 | case DeviceState::SearchingForTag: | ||
| 164 | case DeviceState::TagRemoved: | ||
| 165 | device_state = DeviceState::Initialized; | ||
| 166 | break; | ||
| 167 | default: | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 171 | rb.Push(ResultSuccess); | ||
| 172 | } | ||
| 173 | 126 | ||
| 174 | void Mount(Kernel::HLERequestContext& ctx) { | 127 | void IUser::Unmount(Kernel::HLERequestContext& ctx) { |
| 175 | LOG_DEBUG(Service_NFP, "called"); | 128 | LOG_DEBUG(Service_NFP, "called"); |
| 176 | 129 | ||
| 177 | device_state = DeviceState::TagNearby; | 130 | device_state = DeviceState::TagFound; |
| 178 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 179 | rb.Push(ResultSuccess); | ||
| 180 | } | ||
| 181 | 131 | ||
| 182 | void Unmount(Kernel::HLERequestContext& ctx) { | 132 | IPC::ResponseBuilder rb{ctx, 2}; |
| 183 | LOG_DEBUG(Service_NFP, "called"); | 133 | rb.Push(ResultSuccess); |
| 134 | } | ||
| 184 | 135 | ||
| 185 | device_state = DeviceState::TagFound; | 136 | void IUser::OpenApplicationArea(Kernel::HLERequestContext& ctx) { |
| 137 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | ||
| 138 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 139 | rb.Push(ErrCodes::ERR_NO_APPLICATION_AREA); | ||
| 140 | } | ||
| 186 | 141 | ||
| 187 | IPC::ResponseBuilder rb{ctx, 2}; | 142 | void IUser::GetApplicationArea(Kernel::HLERequestContext& ctx) { |
| 188 | rb.Push(ResultSuccess); | 143 | LOG_WARNING(Service_NFP, "(STUBBED) called"); |
| 189 | } | ||
| 190 | 144 | ||
| 191 | void OpenApplicationArea(Kernel::HLERequestContext& ctx) { | 145 | // TODO(ogniK): Pull application area from amiibo |
| 192 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | ||
| 193 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 194 | rb.Push(ErrCodes::ERR_NO_APPLICATION_AREA); | ||
| 195 | } | ||
| 196 | 146 | ||
| 197 | void GetApplicationArea(Kernel::HLERequestContext& ctx) { | 147 | IPC::ResponseBuilder rb{ctx, 3}; |
| 198 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | 148 | rb.Push(ResultSuccess); |
| 149 | rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub | ||
| 150 | } | ||
| 199 | 151 | ||
| 200 | // TODO(ogniK): Pull application area from amiibo | 152 | void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) { |
| 153 | LOG_DEBUG(Service_NFP, "called"); | ||
| 201 | 154 | ||
| 202 | IPC::ResponseBuilder rb{ctx, 3}; | 155 | IPC::ResponseBuilder rb{ctx, 2}; |
| 203 | rb.Push(ResultSuccess); | 156 | const auto& amiibo = nfp_interface.GetAmiiboBuffer(); |
| 204 | rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub | 157 | const TagInfo tag_info{ |
| 205 | } | 158 | .uuid = amiibo.uuid, |
| 159 | .uuid_length = static_cast<u8>(amiibo.uuid.size()), | ||
| 160 | .protocol = 1, // TODO(ogniK): Figure out actual values | ||
| 161 | .tag_type = 2, | ||
| 162 | }; | ||
| 163 | ctx.WriteBuffer(tag_info); | ||
| 164 | rb.Push(ResultSuccess); | ||
| 165 | } | ||
| 206 | 166 | ||
| 207 | void GetTagInfo(Kernel::HLERequestContext& ctx) { | 167 | void IUser::GetRegisterInfo(Kernel::HLERequestContext& ctx) { |
| 208 | LOG_DEBUG(Service_NFP, "called"); | 168 | LOG_WARNING(Service_NFP, "(STUBBED) called"); |
| 209 | |||
| 210 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 211 | const auto& amiibo = nfp_interface.GetAmiiboBuffer(); | ||
| 212 | const TagInfo tag_info{ | ||
| 213 | .uuid = amiibo.uuid, | ||
| 214 | .uuid_length = static_cast<u8>(amiibo.uuid.size()), | ||
| 215 | .padding_1 = {}, | ||
| 216 | .protocol = 1, // TODO(ogniK): Figure out actual values | ||
| 217 | .tag_type = 2, | ||
| 218 | .padding_2 = {}, | ||
| 219 | }; | ||
| 220 | ctx.WriteBuffer(tag_info); | ||
| 221 | rb.Push(ResultSuccess); | ||
| 222 | } | ||
| 223 | 169 | ||
| 224 | void GetRegisterInfo(Kernel::HLERequestContext& ctx) { | 170 | // TODO(ogniK): Pull Mii and owner data from amiibo |
| 225 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | ||
| 226 | 171 | ||
| 227 | // TODO(ogniK): Pull Mii and owner data from amiibo | 172 | IPC::ResponseBuilder rb{ctx, 2}; |
| 173 | rb.Push(ResultSuccess); | ||
| 174 | } | ||
| 228 | 175 | ||
| 229 | IPC::ResponseBuilder rb{ctx, 2}; | 176 | void IUser::GetCommonInfo(Kernel::HLERequestContext& ctx) { |
| 230 | rb.Push(ResultSuccess); | 177 | LOG_WARNING(Service_NFP, "(STUBBED) called"); |
| 231 | } | ||
| 232 | 178 | ||
| 233 | void GetCommonInfo(Kernel::HLERequestContext& ctx) { | 179 | // TODO(ogniK): Pull common information from amiibo |
| 234 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | ||
| 235 | 180 | ||
| 236 | // TODO(ogniK): Pull common information from amiibo | 181 | CommonInfo common_info{}; |
| 182 | common_info.application_area_size = 0; | ||
| 183 | ctx.WriteBuffer(common_info); | ||
| 237 | 184 | ||
| 238 | CommonInfo common_info{}; | 185 | IPC::ResponseBuilder rb{ctx, 2}; |
| 239 | common_info.application_area_size = 0; | 186 | rb.Push(ResultSuccess); |
| 240 | ctx.WriteBuffer(common_info); | 187 | } |
| 241 | 188 | ||
| 242 | IPC::ResponseBuilder rb{ctx, 2}; | 189 | void IUser::GetModelInfo(Kernel::HLERequestContext& ctx) { |
| 243 | rb.Push(ResultSuccess); | 190 | LOG_DEBUG(Service_NFP, "called"); |
| 244 | } | ||
| 245 | 191 | ||
| 246 | void GetModelInfo(Kernel::HLERequestContext& ctx) { | 192 | IPC::ResponseBuilder rb{ctx, 2}; |
| 247 | LOG_DEBUG(Service_NFP, "called"); | 193 | const auto& amiibo = nfp_interface.GetAmiiboBuffer(); |
| 194 | ctx.WriteBuffer(amiibo.model_info); | ||
| 195 | rb.Push(ResultSuccess); | ||
| 196 | } | ||
| 248 | 197 | ||
| 249 | IPC::ResponseBuilder rb{ctx, 2}; | 198 | void IUser::AttachActivateEvent(Kernel::HLERequestContext& ctx) { |
| 250 | const auto& amiibo = nfp_interface.GetAmiiboBuffer(); | 199 | IPC::RequestParser rp{ctx}; |
| 251 | ctx.WriteBuffer(amiibo.model_info); | 200 | const u64 dev_handle = rp.Pop<u64>(); |
| 252 | rb.Push(ResultSuccess); | 201 | LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); |
| 253 | } | ||
| 254 | 202 | ||
| 255 | void AttachActivateEvent(Kernel::HLERequestContext& ctx) { | 203 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 256 | IPC::RequestParser rp{ctx}; | 204 | rb.Push(ResultSuccess); |
| 257 | const u64 dev_handle = rp.Pop<u64>(); | 205 | rb.PushCopyObjects(nfp_interface.GetNFCEvent()); |
| 258 | LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); | 206 | has_attached_handle = true; |
| 207 | } | ||
| 259 | 208 | ||
| 260 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 209 | void IUser::AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { |
| 261 | rb.Push(ResultSuccess); | 210 | IPC::RequestParser rp{ctx}; |
| 262 | rb.PushCopyObjects(nfp_interface.GetNFCEvent()); | 211 | const u64 dev_handle = rp.Pop<u64>(); |
| 263 | has_attached_handle = true; | 212 | LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); |
| 264 | } | ||
| 265 | 213 | ||
| 266 | void AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { | 214 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 267 | IPC::RequestParser rp{ctx}; | 215 | rb.Push(ResultSuccess); |
| 268 | const u64 dev_handle = rp.Pop<u64>(); | 216 | rb.PushCopyObjects(deactivate_event.GetReadableEvent()); |
| 269 | LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); | 217 | } |
| 270 | 218 | ||
| 271 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 219 | void IUser::GetState(Kernel::HLERequestContext& ctx) { |
| 272 | rb.Push(ResultSuccess); | 220 | LOG_DEBUG(Service_NFC, "called"); |
| 273 | rb.PushCopyObjects(deactivate_event.GetReadableEvent()); | ||
| 274 | } | ||
| 275 | 221 | ||
| 276 | void GetState(Kernel::HLERequestContext& ctx) { | 222 | IPC::ResponseBuilder rb{ctx, 3, 0}; |
| 277 | LOG_DEBUG(Service_NFC, "called"); | 223 | rb.Push(ResultSuccess); |
| 224 | rb.PushRaw<u32>(static_cast<u32>(state)); | ||
| 225 | } | ||
| 278 | 226 | ||
| 279 | IPC::ResponseBuilder rb{ctx, 3, 0}; | 227 | void IUser::GetDeviceState(Kernel::HLERequestContext& ctx) { |
| 280 | rb.Push(ResultSuccess); | 228 | LOG_DEBUG(Service_NFP, "called"); |
| 281 | rb.PushRaw<u32>(static_cast<u32>(state)); | ||
| 282 | } | ||
| 283 | 229 | ||
| 284 | void GetDeviceState(Kernel::HLERequestContext& ctx) { | 230 | IPC::ResponseBuilder rb{ctx, 3}; |
| 285 | LOG_DEBUG(Service_NFP, "called"); | 231 | rb.Push(ResultSuccess); |
| 232 | rb.Push<u32>(static_cast<u32>(device_state)); | ||
| 233 | } | ||
| 286 | 234 | ||
| 287 | IPC::ResponseBuilder rb{ctx, 3}; | 235 | void IUser::GetNpadId(Kernel::HLERequestContext& ctx) { |
| 288 | rb.Push(ResultSuccess); | 236 | IPC::RequestParser rp{ctx}; |
| 289 | rb.Push<u32>(static_cast<u32>(device_state)); | 237 | const u64 dev_handle = rp.Pop<u64>(); |
| 290 | } | 238 | LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); |
| 291 | 239 | ||
| 292 | void GetNpadId(Kernel::HLERequestContext& ctx) { | 240 | IPC::ResponseBuilder rb{ctx, 3}; |
| 293 | IPC::RequestParser rp{ctx}; | 241 | rb.Push(ResultSuccess); |
| 294 | const u64 dev_handle = rp.Pop<u64>(); | 242 | rb.Push<u32>(npad_id); |
| 295 | LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); | 243 | } |
| 296 | 244 | ||
| 297 | IPC::ResponseBuilder rb{ctx, 3}; | 245 | void IUser::GetApplicationAreaSize(Kernel::HLERequestContext& ctx) { |
| 298 | rb.Push(ResultSuccess); | 246 | LOG_WARNING(Service_NFP, "(STUBBED) called"); |
| 299 | rb.Push<u32>(npad_id); | 247 | // We don't need to worry about this since we can just open the file |
| 300 | } | 248 | IPC::ResponseBuilder rb{ctx, 3}; |
| 249 | rb.Push(ResultSuccess); | ||
| 250 | rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub | ||
| 251 | } | ||
| 301 | 252 | ||
| 302 | void GetApplicationAreaSize(Kernel::HLERequestContext& ctx) { | 253 | void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { |
| 303 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | 254 | LOG_WARNING(Service_NFP, "(STUBBED) called"); |
| 304 | // We don't need to worry about this since we can just open the file | ||
| 305 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 306 | rb.Push(ResultSuccess); | ||
| 307 | rb.PushRaw<u32>(0); // This is from the GetCommonInfo stub | ||
| 308 | } | ||
| 309 | 255 | ||
| 310 | void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { | 256 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 311 | LOG_WARNING(Service_NFP, "(STUBBED) called"); | 257 | rb.Push(ResultSuccess); |
| 258 | rb.PushCopyObjects(availability_change_event.GetReadableEvent()); | ||
| 259 | } | ||
| 312 | 260 | ||
| 313 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 261 | Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, |
| 314 | rb.Push(ResultSuccess); | 262 | const char* name) |
| 315 | rb.PushCopyObjects(availability_change_event.GetReadableEvent()); | 263 | : ServiceFramework{system_, name}, nfc_tag_load{system.Kernel()}, module{std::move(module_)} { |
| 316 | } | 264 | Kernel::KAutoObject::Create(std::addressof(nfc_tag_load)); |
| 265 | nfc_tag_load.Initialize("IUser:NFCTagDetected"); | ||
| 266 | } | ||
| 317 | 267 | ||
| 318 | Module::Interface& nfp_interface; | 268 | Module::Interface::~Interface() = default; |
| 319 | KernelHelpers::ServiceContext& service_context; | ||
| 320 | |||
| 321 | bool has_attached_handle{}; | ||
| 322 | const u64 device_handle{0}; // Npad device 1 | ||
| 323 | const u32 npad_id{0}; // Player 1 controller | ||
| 324 | State state{State::NonInitialized}; | ||
| 325 | DeviceState device_state{DeviceState::Initialized}; | ||
| 326 | Kernel::KEvent* deactivate_event; | ||
| 327 | Kernel::KEvent* availability_change_event; | ||
| 328 | }; | ||
| 329 | 269 | ||
| 330 | void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { | 270 | void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) { |
| 331 | LOG_DEBUG(Service_NFP, "called"); | 271 | LOG_DEBUG(Service_NFP, "called"); |
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h index 95c127efb..8d9db880a 100644 --- a/src/core/hle/service/nfp/nfp.h +++ b/src/core/hle/service/nfp/nfp.h | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "core/hle/service/kernel_helpers.h" | 10 | #include "core/hle/service/kernel_helpers.h" |
| 11 | #include "core/hle/kernel/k_event.h" | ||
| 12 | #include "core/hle/service/mii/manager.h" | ||
| 11 | #include "core/hle/service/service.h" | 13 | #include "core/hle/service/service.h" |
| 12 | 14 | ||
| 13 | namespace Kernel { | 15 | namespace Kernel { |
| @@ -16,6 +18,106 @@ class KEvent; | |||
| 16 | 18 | ||
| 17 | namespace Service::NFP { | 19 | namespace Service::NFP { |
| 18 | 20 | ||
| 21 | enum class ServiceType : u32 { | ||
| 22 | User = 0, | ||
| 23 | Debug = 1, | ||
| 24 | System = 2, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum class State : u32 { | ||
| 28 | NonInitialized = 0, | ||
| 29 | Initialized = 1, | ||
| 30 | }; | ||
| 31 | |||
| 32 | enum class DeviceState : u32 { | ||
| 33 | Initialized = 0, | ||
| 34 | SearchingForTag = 1, | ||
| 35 | TagFound = 2, | ||
| 36 | TagRemoved = 3, | ||
| 37 | TagMounted = 4, | ||
| 38 | Unaviable = 5, | ||
| 39 | Finalized = 6 | ||
| 40 | }; | ||
| 41 | |||
| 42 | enum class MountTarget : u32 { | ||
| 43 | Rom = 1, | ||
| 44 | Ram = 2, | ||
| 45 | All = 3, | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct TagInfo { | ||
| 49 | std::array<u8, 10> uuid; | ||
| 50 | u8 uuid_length; | ||
| 51 | INSERT_PADDING_BYTES(0x15); | ||
| 52 | u32_le protocol; | ||
| 53 | u32_le tag_type; | ||
| 54 | INSERT_PADDING_BYTES(0x2c); | ||
| 55 | }; | ||
| 56 | static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size"); | ||
| 57 | |||
| 58 | struct CommonInfo { | ||
| 59 | u16_be last_write_year; | ||
| 60 | u8 last_write_month; | ||
| 61 | u8 last_write_day; | ||
| 62 | u16_be write_counter; | ||
| 63 | u16_be version; | ||
| 64 | u32_be application_area_size; | ||
| 65 | INSERT_PADDING_BYTES(0x34); | ||
| 66 | }; | ||
| 67 | static_assert(sizeof(CommonInfo) == 0x40, "CommonInfo is an invalid size"); | ||
| 68 | |||
| 69 | struct ModelInfo { | ||
| 70 | std::array<u8, 0x8> ammibo_id; | ||
| 71 | INSERT_PADDING_BYTES(0x38); | ||
| 72 | }; | ||
| 73 | static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); | ||
| 74 | |||
| 75 | struct RegisterInfo { | ||
| 76 | Service::Mii::MiiInfo mii; | ||
| 77 | u16_be first_write_year; | ||
| 78 | u8 first_write_month; | ||
| 79 | u8 first_write_day; | ||
| 80 | std::array<u8, 11> amiibo_name; | ||
| 81 | INSERT_PADDING_BYTES(0x99); | ||
| 82 | }; | ||
| 83 | // static_assert(sizeof(RegisterInfo) == 0x106, "RegisterInfo is an invalid size"); | ||
| 84 | |||
| 85 | class IUser final : public ServiceFramework<IUser> { | ||
| 86 | public: | ||
| 87 | explicit IUser(Module::Interface& nfp_interface_, Core::System& system_); | ||
| 88 | |||
| 89 | private: | ||
| 90 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 91 | void Finalize(Kernel::HLERequestContext& ctx); | ||
| 92 | void ListDevices(Kernel::HLERequestContext& ctx); | ||
| 93 | void StartDetection(Kernel::HLERequestContext& ctx); | ||
| 94 | void StopDetection(Kernel::HLERequestContext& ctx); | ||
| 95 | void Mount(Kernel::HLERequestContext& ctx); | ||
| 96 | void Unmount(Kernel::HLERequestContext& ctx); | ||
| 97 | void OpenApplicationArea(Kernel::HLERequestContext& ctx); | ||
| 98 | void GetApplicationArea(Kernel::HLERequestContext& ctx); | ||
| 99 | void GetTagInfo(Kernel::HLERequestContext& ctx); | ||
| 100 | void GetRegisterInfo(Kernel::HLERequestContext& ctx); | ||
| 101 | void GetCommonInfo(Kernel::HLERequestContext& ctx); | ||
| 102 | void GetModelInfo(Kernel::HLERequestContext& ctx); | ||
| 103 | void AttachActivateEvent(Kernel::HLERequestContext& ctx); | ||
| 104 | void AttachDeactivateEvent(Kernel::HLERequestContext& ctx); | ||
| 105 | void GetState(Kernel::HLERequestContext& ctx); | ||
| 106 | void GetDeviceState(Kernel::HLERequestContext& ctx); | ||
| 107 | void GetNpadId(Kernel::HLERequestContext& ctx); | ||
| 108 | void GetApplicationAreaSize(Kernel::HLERequestContext& ctx); | ||
| 109 | void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx); | ||
| 110 | |||
| 111 | bool has_attached_handle{}; | ||
| 112 | const u64 device_handle{0}; // Npad device 1 | ||
| 113 | const u32 npad_id{0}; // Player 1 controller | ||
| 114 | State state{State::NonInitialized}; | ||
| 115 | DeviceState device_state{DeviceState::Initialized}; | ||
| 116 | Module::Interface& nfp_interface; | ||
| 117 | Kernel::KEvent deactivate_event; | ||
| 118 | Kernel::KEvent availability_change_event; | ||
| 119 | }; | ||
| 120 | |||
| 19 | class Module final { | 121 | class Module final { |
| 20 | public: | 122 | public: |
| 21 | class Interface : public ServiceFramework<Interface> { | 123 | class Interface : public ServiceFramework<Interface> { |