Compare commits

..

91 Commits

Author SHA1 Message Date
Liam
dee792937f vulkan_device: add names for more driverID enumeration values 2023-11-24 12:00:41 -05:00
liamwhite
093eb075a6 Merge pull request #12140 from liamwhite/qcr-unreachable
query_cache: demote report synced unreachable to assert
2023-11-24 00:09:00 -05:00
liamwhite
0b766e4523 Merge pull request #12076 from german77/resource
service: hid: Create appropriate hid resources
2023-11-23 12:36:19 -05:00
Liam
453fd47030 query_cache: demote report synced unreachable to assert 2023-11-23 09:33:02 -05:00
liamwhite
91c12db070 Merge pull request #12123 from merryhime/explicit-this
Explicit this
2023-11-21 22:17:42 -05:00
Merry
b088a448cd game_list_worker: Explicit caputure of 'this' 2023-11-21 22:57:47 +00:00
Merry
c4f6c3b00b shared_widget: Explicit capture of 'this' 2023-11-21 22:57:09 +00:00
liamwhite
cddb28cf26 Merge pull request #12107 from daisymlleung/patch-1
Stub CheckBlockedUserListAvailability for Super Bomberman R 2
2023-11-21 09:19:41 -05:00
liamwhite
538e137bca Merge pull request #12100 from t895/android-translations
translations: Add android translations to transifex config
2023-11-21 09:19:34 -05:00
liamwhite
e69118042f Merge pull request #12045 from liamwhite/codec-refactor
video_core: refactor video frame and packet parsing
2023-11-21 09:19:26 -05:00
liamwhite
a6b8d85b34 Merge pull request #11984 from lat9nq/lupdate
shared_translation: Call tr more directly
2023-11-21 09:19:13 -05:00
Narr the Reg
cff2d0e19e service: hid: Create appropriate hid resources 2023-11-20 17:19:17 -06:00
Narr the Reg
8da5bd27e9 Merge pull request #12011 from Macj0rdan/controller-applet
Implemented qlaunch version of the controller applet
2023-11-20 16:53:33 -06:00
daisymlleung
0216aa55b4 Stub CheckBlockedUserListAvailability 2023-11-21 01:57:58 +08:00
t895
0298c2cc5d translations: Add android translations to transifex config 2023-11-20 10:37:09 -05:00
liamwhite
00dcf69ce8 Merge pull request #12093 from t895/zip-intent
android: Use file picker intent for save exporter
2023-11-20 09:38:44 -05:00
liamwhite
1ea0890a36 Merge pull request #12092 from t895/recent-games-default
android: Select recently played games by default in search tab
2023-11-20 09:38:36 -05:00
liamwhite
a77feca086 Merge pull request #12091 from t895/silly-speed
android: Allow up to 400% for the limit speed percent setting
2023-11-20 09:38:21 -05:00
Narr the Reg
99a8f7fb72 Merge pull request #12097 from Squall-Leonhart/ResourceToGetResource
service: hid: Ensure resource manager is initialized
2023-11-19 20:10:38 -06:00
Squall-Leonhart
8ae26df15c service: hid: Ensure resource manager is initialized
Ensures the proper initialization of the IActiveVibrationDeviceList. By using GetResourceManager() instead of resource_manager, we make sure that the IActiveVibrationDeviceListis initialized before it's used, preventing potential null issues.

Fixes #12088
2023-11-20 11:43:56 +11:00
t895
82a4a67f6b android: Use file picker intent for save exporter 2023-11-19 17:52:53 -05:00
t895
8e93a9a9ef android: Use path instead of programId for recently added / played key 2023-11-19 16:00:41 -05:00
t895
23c1f7c72f android: Select recently played games by default in search tab 2023-11-19 15:57:05 -05:00
t895
d3ed771f39 android: Allow up to 400% for the limit speed percent setting 2023-11-19 15:36:25 -05:00
liamwhite
12fba361bd Merge pull request #12083 from liamwhite/viewport
renderer_vulkan: ignore viewport stores on non-supporting drivers
2023-11-19 14:09:25 -05:00
liamwhite
6bcde572dd Merge pull request #12085 from liamwhite/build-fix
qt: fix linux build
2023-11-19 14:09:18 -05:00
FrozenAra
cb004d1ba1 Implemented qlaunch version of the controller applet 2023-11-19 18:38:58 +01:00
Liam
20a17607ae qt: fix linux build 2023-11-19 11:49:51 -05:00
Liam
473caaff5b renderer_vulkan: ignore viewport stores on non-supporting drivers 2023-11-19 11:27:12 -05:00
liamwhite
787552f832 Merge pull request #12081 from FernandoS27/check-out-on-your-broke-crypto-friends
Vulkan: Be more generous with pipeline workers for Android
2023-11-19 11:16:19 -05:00
liamwhite
5f945e2fcd Merge pull request #12036 from FernandoS27/you-should-have-more-than-one-towel
Query Cache: Disable write syncing on Android
2023-11-19 09:52:22 -05:00
liamwhite
c08da2d6ad Merge pull request #11792 from boludoz/new-shortcut
Improved shortcut: add games in applist for Windows, question for sta…
2023-11-19 09:50:49 -05:00
liamwhite
4458920799 Merge pull request #12066 from ameerj/nvidia-nsanity
shader_recompiler: add byteswap pattern workaround for Nvidia
2023-11-19 09:49:45 -05:00
liamwhite
61fed8a3a6 Merge pull request #12068 from ameerj/glasm-xfb-fixes
gl_graphics_pipeline: GLASM: Fix transform feedback attribs buffer mode
2023-11-19 09:49:38 -05:00
liamwhite
efb3165e3d Merge pull request #12072 from FernandoS27/winter-is-2-seconds-too-soon
Buffer Cache: Eliminate clears on Indirect buffers
2023-11-19 09:49:30 -05:00
Fernando Sahmkow
a493ba76b4 Vulkan: Be more generous with pipeline workers for Android 2023-11-19 14:54:15 +01:00
Fernando Sahmkow
ae60a5657e Buffer Cache: Eliminate clears on Indirect buffers 2023-11-18 19:26:14 +01:00
Ameer J
feb60de5c3 shader_recompiler: Fix spelling of "derivate" (#12067) 2023-11-18 13:39:47 +01:00
Ameer J
c67644f1da gl_graphics_pipeline: GLASM: Fix transform feedback attribs buffer mode
GL_SEPARATE_ATTRIBS only applies when multiple buffers are being used, else GL_INTERLEAVED_ATTRIBS handles the cases for a single buffer with potentially more than one attribute
2023-11-18 00:44:05 -05:00
Ameer J
9343b81afd shader_recompiler: add byteswap pattern workaround for Nvidia 2023-11-17 22:29:12 -05:00
liamwhite
71f53b4218 Merge pull request #12058 from liamwhite/opus-again
opus: fix stereo stream count check in multistream decoder object
2023-11-17 20:41:50 -05:00
liamwhite
f131b0faeb Merge pull request #11912 from liamwhite/nv-graphic-buffer
nvnflinger: use graphic buffer lifetime for map handle
2023-11-17 20:41:34 -05:00
liamwhite
6c64d5aff2 Merge pull request #11917 from liamwhite/abandonment
nvnflinger: implement consumer abandonment
2023-11-17 20:41:23 -05:00
Liam
de594995da opus: fix stereo stream count check in multistream decoder object 2023-11-17 08:26:22 -05:00
liamwhite
4c16a1a26f Merge pull request #12055 from german77/activate
service: hid: Introduce firmware settings and update activate controller calls
2023-11-16 21:28:06 -05:00
Narr the Reg
862e66202c service: hid: Introduce firmware settings and update activate controller calls 2023-11-16 18:51:14 -06:00
liamwhite
2136a46ab7 Merge pull request #12053 from german77/no_functional
service: hid: Implement xpad calls
2023-11-16 16:54:01 -05:00
Narr the Reg
b9c7e5c2c8 service: hid: Implement xpad calls 2023-11-16 11:18:11 -06:00
liamwhite
d86e88a622 Merge pull request #11995 from FernandoS27/you-dont-need-the-new-iphone
Revert PR #11806 and do a proper fix to the memory handling.
2023-11-16 09:17:13 -05:00
liamwhite
7eac28e410 Merge pull request #12038 from german77/no_implement
service: hid: Split hid.cpp into individual interfaces
2023-11-16 09:13:56 -05:00
liamwhite
ea4c92f734 Merge pull request #12007 from german77/moar_buttons
core: hid: Split SL and SR buttons
2023-11-16 09:13:39 -05:00
Narr the Reg
c9cd938dfd service: hid: Split hid.cpp into individual interfaces 2023-11-15 09:59:54 -06:00
Fernando Sahmkow
c9437e5244 Query Cache: Disable write syncing on Android 2023-11-15 02:23:39 +01:00
Fernando Sahmkow
f1806d237f Memory: Fix invalidation handling from the CPU/Services 2023-11-12 14:10:40 +01:00
german77
ae57a99d7d core: hid: Split SL and SR buttons 2023-11-11 21:03:15 -06:00
Fernando Sahmkow
1d03a0fa75 Revert "renderer_vulkan: add locks to avoid scheduler flushes from CPU"
This reverts commit d9dde7e6f3.
2023-11-10 15:40:48 +01:00
Franco M
c9038af29e Fix out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::IconsDir); 2023-11-09 04:53:10 +00:00
Franco M
f3053920bf Minor changes 2023-11-09 03:37:06 +00:00
Franco M
c7b31d24b9 Final change, i think 2023-11-08 21:04:30 +00:00
lat9nq
cb3559539a CMakeLists: Add option to call lupdate directly
qt_create_translation silently fails to run at all on my system. Since
there is no error, I was unable to determine a fix. This sidesteps the
convenience function by setting up the rules ourselves.

This is left as an option since this path likely does not work on
Windows.
2023-11-08 11:54:05 -05:00
lat9nq
71cdfa6ad5 shared_translation: Call tr for each string
Qt can't parse tr called within a macro, so we must call it on each
string.

shared_translation: Remove redundant include
2023-11-08 11:54:01 -05:00
Franco M
8d0d0e1c7a Fixed clang 2023-11-07 02:32:19 +00:00
Franco M
4b8b223db2 modified: src/yuzu/main.cpp 2023-11-05 00:39:43 +00:00
Franco M
728aca7703 Merge branch 'master' into new-shortcut 2023-11-04 21:28:16 -03:00
Liam
a872030a35 nvnflinger: implement consumer abandonment 2023-10-29 23:38:24 -04:00
Liam
79e7d7f4ba nvnflinger: use graphic buffer lifetime for map handle 2023-10-29 22:12:16 -04:00
boludoz
7f62a48ab5 We dont need that 2023-10-27 00:30:35 -03:00
Franco M
b5415b6872 Merge branch 'yuzu-emu:master' into new-shortcut 2023-10-26 19:11:15 -03:00
Franco M
b76a1d987f Merge branch 'yuzu-emu:master' into new-shortcut 2023-10-21 02:25:27 -03:00
boludoz
ae2130470e Reverted dirty code in main. 2023-10-18 19:30:21 -03:00
boludoz
ac6290bea7 TODO: Implement shortcut creation for Apple. 2023-10-18 02:35:23 -03:00
boludoz
4051bbbed7 Useless code removed related to admin privileges, if it is not an error we can add it later, that is what git is for. 2023-10-18 01:26:50 -03:00
boludoz
2a7edda70a Deleted admin requisite (maybe it was another mistake). 2023-10-18 01:20:46 -03:00
Franco M
59b6ada7b7 Merge branch 'yuzu-emu:master' into new-shortcut 2023-10-18 01:06:58 -03:00
boludoz
9908434c14 Final refactorization 2023-10-17 02:57:35 -03:00
Franco M
668a10f9b9 Merge branch 'yuzu-emu:master' into new-shortcut 2023-10-17 01:01:41 -03:00
boludoz
fc4b45ebd3 Moved check. 2023-10-16 23:50:09 -03:00
boludoz
1afe6d51ee More @liamwhite suggestions applied. 2023-10-16 23:42:45 -03:00
boludoz
1ae0f0f3f6 shortcut_stream.close(); fixed 2023-10-16 18:59:21 -03:00
boludoz
de0b35b974 Comment using fmt instead qt. 2023-10-16 16:54:51 -03:00
boludoz
ae88d01d8d .clear() instead = ""; and switch improved. 2023-10-16 16:47:21 -03:00
boludoz
d759de9f96 More missed suggestions 2023-10-16 16:11:24 -03:00
boludoz
89d3e81be8 Sugestions and fixes. 2023-10-16 16:01:46 -03:00
boludoz
71f264c498 Merge branch 'new-shortcut' of https://github.com/boludoz/yuzu into new-shortcut 2023-10-16 03:27:10 -03:00
boludoz
26417da5d3 Some improvements (suggestions) 2023-10-16 03:26:40 -03:00
Franco M
b3b458edf9 Merge branch 'yuzu-emu:master' into new-shortcut 2023-10-16 03:25:11 -03:00
boludoz
74961d4dfb Less code, simpler, better. 2023-10-15 21:40:10 -03:00
boludoz
9ffa1801c7 Typing and formatting errors fixed. 2023-10-15 20:57:06 -03:00
boludoz
4d4fe69223 Unnecessary feature removed 2023-10-15 14:44:23 -03:00
boludoz
0a75519ab5 Fixes and improvements 2023-10-15 03:16:29 -03:00
boludoz
3062a35eb1 Improved shortcut: add games in applist for Windows, question for start game at fullscreen & better unicode support for some Windows path funcs. 2023-10-15 02:02:22 -03:00
137 changed files with 6664 additions and 4881 deletions

View File

@@ -6,3 +6,8 @@ file_filter = <lang>.ts
source_file = en.ts
source_lang = en
type = QT
[o:yuzu-emulator:p:yuzu:r:yuzu-android]
file_filter = ../../src/android/app/src/main/res/values-<lang>/strings.xml
source_file = ../../src/android/app/src/main/res/values/strings.xml
type = ANDROID

View File

@@ -73,7 +73,7 @@ abstract class SettingsItem(
R.string.frame_limit_slider,
R.string.frame_limit_slider_description,
1,
200,
400,
"%"
)
)

View File

@@ -21,6 +21,8 @@ import org.yuzu.yuzu_emu.databinding.FragmentInstallablesBinding
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.model.Installable
import org.yuzu.yuzu_emu.ui.main.MainActivity
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
class InstallableFragment : Fragment() {
private var _binding: FragmentInstallablesBinding? = null
@@ -78,7 +80,15 @@ class InstallableFragment : Fragment() {
R.string.manage_save_data,
R.string.import_export_saves_description,
install = { mainActivity.importSaves.launch(arrayOf("application/zip")) },
export = { mainActivity.exportSave() }
export = {
mainActivity.exportSaves.launch(
"yuzu saves - ${
LocalDateTime.now().format(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
)
}.zip"
)
}
)
} else {
Installable(

View File

@@ -18,8 +18,8 @@ class Game(
val version: String = "",
val isHomebrew: Boolean = false
) : Parcelable {
val keyAddedToLibraryTime get() = "${programId}_AddedToLibraryTime"
val keyLastPlayedTime get() = "${programId}_LastPlayed"
val keyAddedToLibraryTime get() = "${path}_AddedToLibraryTime"
val keyLastPlayedTime get() = "${path}_LastPlayed"
override fun equals(other: Any?): Boolean {
if (other !is Game) {

View File

@@ -6,7 +6,6 @@ package org.yuzu.yuzu_emu.ui.main
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.DocumentsContract
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.WindowManager
@@ -20,7 +19,6 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
@@ -41,7 +39,6 @@ import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
import org.yuzu.yuzu_emu.features.DocumentProvider
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
@@ -53,9 +50,6 @@ import org.yuzu.yuzu_emu.model.TaskViewModel
import org.yuzu.yuzu_emu.utils.*
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.FileOutputStream
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
@@ -73,7 +67,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
// Get first subfolder in saves folder (should be the user folder)
val savesFolderRoot get() = File(savesFolder).listFiles()?.firstOrNull()?.canonicalPath ?: ""
private var lastZipCreated: File? = null
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
@@ -656,75 +649,31 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
}
/**
* Zips the save files located in the given folder path and creates a new zip file with the current date and time.
* @return true if the zip file is successfully created, false otherwise.
*/
private fun zipSave(): Boolean {
try {
val tempFolder = File(getPublicFilesDir().canonicalPath, "temp")
tempFolder.mkdirs()
val saveFolder = File(savesFolderRoot)
val outputZipFile = File(
tempFolder,
"yuzu saves - ${
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
}.zip"
)
outputZipFile.createNewFile()
val result = FileUtil.zipFromInternalStorage(
saveFolder,
savesFolderRoot,
BufferedOutputStream(FileOutputStream(outputZipFile))
)
if (result == TaskState.Failed) {
return false
}
lastZipCreated = outputZipFile
} catch (e: Exception) {
return false
}
return true
}
/**
* Exports the save file located in the given folder path by creating a zip file and sharing it via intent.
*/
fun exportSave() {
CoroutineScope(Dispatchers.IO).launch {
val wasZipCreated = zipSave()
val lastZipFile = lastZipCreated
if (!wasZipCreated || lastZipFile == null) {
withContext(Dispatchers.Main) {
Toast.makeText(
this@MainActivity,
getString(R.string.export_save_failed),
Toast.LENGTH_LONG
).show()
}
return@launch
}
withContext(Dispatchers.Main) {
val file = DocumentFile.fromSingleUri(
this@MainActivity,
DocumentsContract.buildDocumentUri(
DocumentProvider.AUTHORITY,
"${DocumentProvider.ROOT_ID}/temp/${lastZipFile.name}"
)
)!!
val intent = Intent(Intent.ACTION_SEND)
.setDataAndType(file.uri, "application/zip")
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(Intent.EXTRA_STREAM, file.uri)
startForResultExportSave.launch(
Intent.createChooser(
intent,
getString(R.string.share_save_file)
)
)
}
val exportSaves = registerForActivityResult(
ActivityResultContracts.CreateDocument("application/zip")
) { result ->
if (result == null) {
return@registerForActivityResult
}
IndeterminateProgressDialogFragment.newInstance(
this,
R.string.save_files_exporting,
false
) {
val zipResult = FileUtil.zipFromInternalStorage(
File(savesFolderRoot),
savesFolderRoot,
BufferedOutputStream(contentResolver.openOutputStream(result))
)
return@newInstance when (zipResult) {
TaskState.Completed -> getString(R.string.export_success)
TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed)
}
}.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
}
private val startForResultExportSave =

View File

@@ -127,6 +127,7 @@
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingVertical="4dp"
app:checkedChip="@id/chip_recently_played"
app:chipSpacingHorizontal="12dp"
app:singleLine="true"
app:singleSelection="true">

View File

@@ -91,6 +91,7 @@
<string name="manage_save_data">Manage save data</string>
<string name="manage_save_data_description">Save data found. Please select an option below.</string>
<string name="import_export_saves_description">Import or export save files</string>
<string name="save_files_exporting">Exporting save files…</string>
<string name="save_file_imported_success">Imported successfully</string>
<string name="save_file_invalid_zip_structure">Invalid save directory structure</string>
<string name="save_file_invalid_zip_structure_description">The first subfolder name must be the title ID of the game.</string>
@@ -256,6 +257,7 @@
<string name="cancelling">Cancelling</string>
<string name="install">Install</string>
<string name="delete">Delete</string>
<string name="export_success">Exported successfully</string>
<!-- GPU driver installation -->
<string name="select_gpu_driver">Select GPU driver</string>

View File

@@ -12,7 +12,7 @@ bool IsValidChannelCount(u32 channel_count) {
}
bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) {
return total_stream_count > 0 && stereo_stream_count > 0 &&
return total_stream_count > 0 && static_cast<s32>(stereo_stream_count) >= 0 &&
stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count);
}
} // namespace

View File

@@ -148,7 +148,7 @@ Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out
auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
OpusPacketHeader header{ReverseHeader(*header_p)};
LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}",
LOG_TRACE(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}",
header.size, input_data.size_bytes(), in_data.size_bytes());
R_UNLESS(in_data.size_bytes() >= header.size &&

View File

@@ -6,10 +6,11 @@
namespace Settings {
namespace NativeButton {
const std::array<const char*, NumButtons> mapping = {{
"button_a", "button_b", "button_x", "button_y", "button_lstick",
"button_rstick", "button_l", "button_r", "button_zl", "button_zr",
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
"button_ddown", "button_sl", "button_sr", "button_home", "button_screenshot",
"button_a", "button_b", "button_x", "button_y", "button_lstick",
"button_rstick", "button_l", "button_r", "button_zl", "button_zr",
"button_plus", "button_minus", "button_dleft", "button_dup", "button_dright",
"button_ddown", "button_slleft", "button_srleft", "button_home", "button_screenshot",
"button_slright", "button_srright",
}};
}

View File

@@ -29,12 +29,15 @@ enum Values : int {
DRight,
DDown,
SL,
SR,
SLLeft,
SRLeft,
Home,
Screenshot,
SLRight,
SRRight,
NumButtons,
};

View File

@@ -521,17 +521,28 @@ add_library(core STATIC
hle/service/grc/grc.h
hle/service/hid/hid.cpp
hle/service/hid/hid.h
hle/service/hid/hid_debug_server.cpp
hle/service/hid/hid_debug_server.h
hle/service/hid/hid_firmware_settings.cpp
hle/service/hid/hid_firmware_settings.h
hle/service/hid/hid_server.cpp
hle/service/hid/hid_server.h
hle/service/hid/hid_system_server.cpp
hle/service/hid/hid_system_server.h
hle/service/hid/hid_util.h
hle/service/hid/hidbus.cpp
hle/service/hid/hidbus.h
hle/service/hid/irs.cpp
hle/service/hid/irs.h
hle/service/hid/irs_ring_lifo.h
hle/service/hid/resource_manager.cpp
hle/service/hid/resource_manager.h
hle/service/hid/ring_lifo.h
hle/service/hid/xcd.cpp
hle/service/hid/xcd.h
hle/service/hid/errors.h
hle/service/hid/controllers/console_sixaxis.cpp
hle/service/hid/controllers/console_sixaxis.h
hle/service/hid/controllers/console_six_axis.cpp
hle/service/hid/controllers/console_six_axis.h
hle/service/hid/controllers/controller_base.cpp
hle/service/hid/controllers/controller_base.h
hle/service/hid/controllers/debug_pad.cpp
@@ -546,6 +557,10 @@ add_library(core STATIC
hle/service/hid/controllers/npad.h
hle/service/hid/controllers/palma.cpp
hle/service/hid/controllers/palma.h
hle/service/hid/controllers/seven_six_axis.cpp
hle/service/hid/controllers/seven_six_axis.h
hle/service/hid/controllers/six_axis.cpp
hle/service/hid/controllers/six_axis.h
hle/service/hid/controllers/stubbed.cpp
hle/service/hid/controllers/stubbed.h
hle/service/hid/controllers/touchscreen.cpp
@@ -715,6 +730,7 @@ add_library(core STATIC
hle/service/nvnflinger/producer_listener.h
hle/service/nvnflinger/status.h
hle/service/nvnflinger/ui/fence.h
hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h
hle/service/olsc/olsc.cpp

View File

@@ -38,14 +38,6 @@ using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>;
using ConsoleMotionValues = ConsoleMotionInfo;
using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>;
struct TouchFinger {
u64 last_touch{};
Common::Point<float> position{};
u32 id{};
TouchAttribute attribute{};
bool pressed{};
};
// Contains all motion related data that is used on the services
struct ConsoleMotion {
Common::Vec3f accel{};

View File

@@ -8,6 +8,7 @@
#include "common/thread.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/input_converter.h"
#include "core/hle/service/hid/hid_util.h"
namespace Core::HID {
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
@@ -82,7 +83,7 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleInde
}
void EmulatedController::ReloadFromSettings() {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
for (std::size_t index = 0; index < player.buttons.size(); ++index) {
@@ -118,7 +119,7 @@ void EmulatedController::ReloadFromSettings() {
}
void EmulatedController::ReloadColorsFromSettings() {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
// Avoid updating colors if overridden by physical controller
@@ -215,7 +216,7 @@ void EmulatedController::LoadDevices() {
}
void EmulatedController::LoadTASParams() {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
Common::ParamPackage common_params{};
common_params.Set("engine", "tas");
common_params.Set("port", static_cast<int>(player_index));
@@ -243,10 +244,12 @@ void EmulatedController::LoadTASParams() {
tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
tas_button_params[Settings::NativeButton::SL].Set("button", 16);
tas_button_params[Settings::NativeButton::SR].Set("button", 17);
tas_button_params[Settings::NativeButton::SLLeft].Set("button", 16);
tas_button_params[Settings::NativeButton::SRLeft].Set("button", 17);
tas_button_params[Settings::NativeButton::Home].Set("button", 18);
tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
tas_button_params[Settings::NativeButton::SLRight].Set("button", 20);
tas_button_params[Settings::NativeButton::SRRight].Set("button", 21);
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
@@ -262,7 +265,7 @@ void EmulatedController::LoadTASParams() {
}
void EmulatedController::LoadVirtualGamepadParams() {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
Common::ParamPackage common_params{};
common_params.Set("engine", "virtual_gamepad");
common_params.Set("port", static_cast<int>(player_index));
@@ -296,10 +299,12 @@ void EmulatedController::LoadVirtualGamepadParams() {
virtual_button_params[Settings::NativeButton::DUp].Set("button", 13);
virtual_button_params[Settings::NativeButton::DRight].Set("button", 14);
virtual_button_params[Settings::NativeButton::DDown].Set("button", 15);
virtual_button_params[Settings::NativeButton::SL].Set("button", 16);
virtual_button_params[Settings::NativeButton::SR].Set("button", 17);
virtual_button_params[Settings::NativeButton::SLLeft].Set("button", 16);
virtual_button_params[Settings::NativeButton::SRLeft].Set("button", 17);
virtual_button_params[Settings::NativeButton::Home].Set("button", 18);
virtual_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
virtual_button_params[Settings::NativeButton::SLRight].Set("button", 20);
virtual_button_params[Settings::NativeButton::SRRight].Set("button", 21);
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
virtual_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
@@ -611,7 +616,7 @@ bool EmulatedController::IsConfiguring() const {
}
void EmulatedController::SaveCurrentConfig() {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
auto& player = Settings::values.players.GetValue()[player_index];
player.connected = is_connected;
player.controller_type = MapNPadToSettingsType(npad_type);
@@ -867,12 +872,16 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback
controller.npad_button_state.down.Assign(current_status.value);
controller.debug_pad_button_state.d_down.Assign(current_status.value);
break;
case Settings::NativeButton::SL:
case Settings::NativeButton::SLLeft:
controller.npad_button_state.left_sl.Assign(current_status.value);
break;
case Settings::NativeButton::SLRight:
controller.npad_button_state.right_sl.Assign(current_status.value);
break;
case Settings::NativeButton::SR:
case Settings::NativeButton::SRLeft:
controller.npad_button_state.left_sr.Assign(current_status.value);
break;
case Settings::NativeButton::SRRight:
controller.npad_button_state.right_sr.Assign(current_status.value);
break;
case Settings::NativeButton::Home:
@@ -1204,7 +1213,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
if (!output_devices[device_index]) {
return false;
}
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
@@ -1230,7 +1239,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
}
bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
if (!player.vibration_enabled) {
@@ -1640,7 +1649,7 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
}
if (is_connected) {
LOG_WARNING(Service_HID, "Controller {} type changed while it's connected",
NpadIdTypeToIndex(npad_id_type));
Service::HID::NpadIdTypeToIndex(npad_id_type));
}
npad_type = npad_type_;
}
@@ -1890,12 +1899,16 @@ NpadButton EmulatedController::GetTurboButtonMask() const {
case Settings::NativeButton::DDown:
button_mask.down.Assign(1);
break;
case Settings::NativeButton::SL:
case Settings::NativeButton::SLLeft:
button_mask.left_sl.Assign(1);
break;
case Settings::NativeButton::SLRight:
button_mask.right_sl.Assign(1);
break;
case Settings::NativeButton::SR:
case Settings::NativeButton::SRLeft:
button_mask.left_sr.Assign(1);
break;
case Settings::NativeButton::SRRight:
button_mask.right_sr.Assign(1);
break;
default:

View File

@@ -6,6 +6,7 @@
#include "core/hid/emulated_controller.h"
#include "core/hid/emulated_devices.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/hid_util.h"
namespace Core::HID {
@@ -98,11 +99,11 @@ const EmulatedDevices* HIDCore::GetEmulatedDevices() const {
}
EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) {
return GetEmulatedController(IndexToNpadIdType(index));
return GetEmulatedController(Service::HID::IndexToNpadIdType(index));
}
const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t index) const {
return GetEmulatedController(IndexToNpadIdType(index));
return GetEmulatedController(Service::HID::IndexToNpadIdType(index));
}
void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) {

View File

@@ -8,6 +8,7 @@
#include "common/common_types.h"
#include "common/point.h"
#include "common/uuid.h"
#include "common/vector_math.h"
namespace Core::HID {
@@ -218,6 +219,13 @@ enum class NpadIdType : u32 {
Invalid = 0xFFFFFFFF,
};
enum class NpadInterfaceType : u8 {
Bluetooth = 1,
Rail = 2,
Usb = 3,
Embedded = 4,
};
// This is nn::hid::NpadStyleIndex
enum class NpadStyleIndex : u8 {
None = 0,
@@ -356,6 +364,14 @@ struct TouchState {
};
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
struct TouchFinger {
u64 last_touch{};
Common::Point<float> position{};
u32 id{};
TouchAttribute attribute{};
bool pressed{};
};
// This is nn::hid::TouchScreenConfigurationForNx
struct TouchScreenConfigurationForNx {
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
@@ -583,6 +599,29 @@ struct SixAxisSensorIcInformation {
static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8,
"SixAxisSensorIcInformation is an invalid size");
// This is nn::hid::SixAxisSensorAttribute
struct SixAxisSensorAttribute {
union {
u32 raw{};
BitField<0, 1, u32> is_connected;
BitField<1, 1, u32> is_interpolated;
};
};
static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
// This is nn::hid::SixAxisSensorState
struct SixAxisSensorState {
s64 delta_time{};
s64 sampling_number{};
Common::Vec3f accel{};
Common::Vec3f gyro{};
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
SixAxisSensorAttribute attribute{};
INSERT_PADDING_BYTES(4); // Reserved
};
static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
// This is nn::hid::VibrationDeviceHandle
struct VibrationDeviceHandle {
NpadStyleIndex npad_type{NpadStyleIndex::None};
@@ -693,60 +732,4 @@ struct UniquePadId {
};
static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size");
/// Converts a NpadIdType to an array index.
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
switch (npad_id_type) {
case NpadIdType::Player1:
return 0;
case NpadIdType::Player2:
return 1;
case NpadIdType::Player3:
return 2;
case NpadIdType::Player4:
return 3;
case NpadIdType::Player5:
return 4;
case NpadIdType::Player6:
return 5;
case NpadIdType::Player7:
return 6;
case NpadIdType::Player8:
return 7;
case NpadIdType::Handheld:
return 8;
case NpadIdType::Other:
return 9;
default:
return 0;
}
}
/// Converts an array index to a NpadIdType
constexpr NpadIdType IndexToNpadIdType(size_t index) {
switch (index) {
case 0:
return NpadIdType::Player1;
case 1:
return NpadIdType::Player2;
case 2:
return NpadIdType::Player3;
case 3:
return NpadIdType::Player4;
case 4:
return NpadIdType::Player5;
case 5:
return NpadIdType::Player6;
case 6:
return NpadIdType::Player7;
case 7:
return NpadIdType::Player8;
case 8:
return NpadIdType::Handheld;
case 9:
return NpadIdType::Other;
default:
return NpadIdType::Invalid;
}
}
} // namespace Core::HID

View File

@@ -5,21 +5,22 @@
#include "core/hid/hid_types.h"
#include "core/hid/input_interpreter.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/hid_server.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/sm/sm.h"
InputInterpreter::InputInterpreter(Core::System& system)
: npad{system.ServiceManager()
.GetService<Service::HID::Hid>("hid")
->GetAppletResource()
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)} {
.GetService<Service::HID::IHidServer>("hid")
->GetResourceManager()
->GetNpad()} {
ResetButtonStates();
}
InputInterpreter::~InputInterpreter() = default;
void InputInterpreter::PollInput() {
const auto button_state = npad.GetAndResetPressState();
const auto button_state = npad->GetAndResetPressState();
previous_index = current_index;
current_index = (current_index + 1) % button_states.size();

View File

@@ -16,7 +16,7 @@ enum class NpadButton : u64;
}
namespace Service::HID {
class Controller_NPad;
class NPad;
}
/**
@@ -101,7 +101,7 @@ public:
}
private:
Service::HID::Controller_NPad& npad;
std::shared_ptr<Service::HID::NPad> npad;
/// Stores 9 consecutive button states polled from HID.
std::array<Core::HID::NpadButton, 9> button_states{};

View File

@@ -13,6 +13,7 @@
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hid/hid_types.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/result.h"
@@ -21,6 +22,7 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applet_cabinet.h"
#include "core/hle/service/am/applets/applet_controller.h"
#include "core/hle/service/am/applets/applet_mii_edit_types.h"
#include "core/hle/service/am/applets/applet_profile_select.h"
#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
@@ -35,6 +37,7 @@
#include "core/hle/service/caps/caps_su.h"
#include "core/hle/service/caps/caps_types.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
@@ -73,7 +76,7 @@ IWindowController::IWindowController(Core::System& system_)
static const FunctionInfo functions[] = {
{0, nullptr, "CreateWindow"},
{1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
{2, nullptr, "GetAppletResourceUserIdOfCallerApplet"},
{2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
{10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
{11, nullptr, "ReleaseForegroundRights"},
{12, nullptr, "RejectToChangeIntoBackground"},
@@ -97,6 +100,16 @@ void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
rb.Push<u64>(process_id);
}
void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
const u64 process_id = 0;
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u64>(process_id);
}
void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
@@ -1565,7 +1578,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
{6, nullptr, "GetPopInteractiveInDataEvent"},
{10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
{11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
{12, nullptr, "GetMainAppletIdentityInfo"},
{12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
{13, nullptr, "CanUseApplicationCore"},
{14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
{15, nullptr, "GetMainAppletApplicationControlProperty"},
@@ -1609,6 +1622,9 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
case Applets::AppletId::SoftwareKeyboard:
PushInShowSoftwareKeyboard();
break;
case Applets::AppletId::Controller:
PushInShowController();
break;
default:
break;
}
@@ -1666,13 +1682,33 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
rb.PushRaw(applet_info);
}
void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
struct AppletIdentityInfo {
Applets::AppletId applet_id;
INSERT_PADDING_BYTES(0x4);
u64 application_id;
};
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
LOG_WARNING(Service_AM, "(STUBBED) called");
const AppletIdentityInfo applet_info{
.applet_id = Applets::AppletId::QLaunch,
.application_id = 0x0100000000001000ull,
};
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.PushRaw(applet_info);
}
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
struct AppletIdentityInfo {
Applets::AppletId applet_id;
INSERT_PADDING_BYTES(0x4);
u64 application_id;
};
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
LOG_WARNING(Service_AM, "(STUBBED) called");
const AppletIdentityInfo applet_info{
@@ -1737,6 +1773,55 @@ void ILibraryAppletSelfAccessor::PushInShowAlbum() {
queue_data.emplace_back(std::move(settings_data));
}
void ILibraryAppletSelfAccessor::PushInShowController() {
const Applets::CommonArguments common_args = {
.arguments_version = Applets::CommonArgumentVersion::Version3,
.size = Applets::CommonArgumentSize::Version3,
.library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
.theme_color = Applets::ThemeColor::BasicBlack,
.play_startup_sound = true,
.system_tick = system.CoreTiming().GetClockTicks(),
};
Applets::ControllerSupportArgNew user_args = {
.header = {.player_count_min = 1,
.player_count_max = 4,
.enable_take_over_connection = true,
.enable_left_justify = false,
.enable_permit_joy_dual = true,
.enable_single_mode = false,
.enable_identification_color = false},
.identification_colors = {},
.enable_explain_text = false,
.explain_text = {},
};
Applets::ControllerSupportArgPrivate private_args = {
.arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
.arg_size = sizeof(Applets::ControllerSupportArgNew),
.is_home_menu = true,
.flag_1 = true,
.mode = Applets::ControllerSupportMode::ShowControllerSupport,
.caller = Applets::ControllerSupportCaller::
Application, // switchbrew: Always zero except with
// ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
// which sets this to the input param
.style_set = Core::HID::NpadStyleSet::None,
.joy_hold_type = 0,
};
std::vector<u8> common_args_data(sizeof(common_args));
std::vector<u8> private_args_data(sizeof(private_args));
std::vector<u8> user_args_data(sizeof(user_args));
std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
queue_data.emplace_back(std::move(common_args_data));
queue_data.emplace_back(std::move(private_args_data));
queue_data.emplace_back(std::move(user_args_data));
}
void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
const Applets::CommonArguments arguments{
.arguments_version = Applets::CommonArgumentVersion::Version3,

View File

@@ -87,6 +87,7 @@ public:
private:
void GetAppletResourceUserId(HLERequestContext& ctx);
void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
void AcquireForegroundRights(HLERequestContext& ctx);
};
@@ -345,6 +346,7 @@ private:
void PopInData(HLERequestContext& ctx);
void PushOutData(HLERequestContext& ctx);
void GetLibraryAppletInfo(HLERequestContext& ctx);
void GetMainAppletIdentityInfo(HLERequestContext& ctx);
void ExitProcessAndReturn(HLERequestContext& ctx);
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
void GetDesirableKeyboardLayout(HLERequestContext& ctx);
@@ -355,6 +357,7 @@ private:
void PushInShowCabinetData();
void PushInShowMiiEditData();
void PushInShowSoftwareKeyboard();
void PushInShowController();
std::deque<std::vector<u8>> queue_data;
};

View File

@@ -56,7 +56,7 @@ enum class ControllerSupportResult : u32 {
struct ControllerSupportArgPrivate {
u32 arg_private_size{};
u32 arg_size{};
bool flag_0{};
bool is_home_menu{};
bool flag_1{};
ControllerSupportMode mode{};
ControllerSupportCaller caller{};

View File

@@ -127,7 +127,7 @@ public:
private:
void GetCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_BTM, "called");
LOG_WARNING(Service_BTM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
@@ -263,13 +263,13 @@ public:
explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "StartGamepadPairing"},
{1, nullptr, "CancelGamepadPairing"},
{0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"},
{1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"},
{2, nullptr, "ClearGamepadPairingDatabase"},
{3, nullptr, "GetPairedGamepadCount"},
{4, nullptr, "EnableRadio"},
{5, nullptr, "DisableRadio"},
{6, nullptr, "GetRadioOnOff"},
{6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"},
{7, nullptr, "AcquireRadioEvent"},
{8, nullptr, "AcquireGamepadPairingEvent"},
{9, nullptr, "IsGamepadPairingStarted"},
@@ -280,18 +280,58 @@ public:
{14, nullptr, "AcquireAudioDeviceConnectionEvent"},
{15, nullptr, "ConnectAudioDevice"},
{16, nullptr, "IsConnectingAudioDevice"},
{17, nullptr, "GetConnectedAudioDevices"},
{17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"},
{18, nullptr, "DisconnectAudioDevice"},
{19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"},
{20, nullptr, "GetPairedAudioDevices"},
{21, nullptr, "RemoveAudioDevicePairing"},
{22, nullptr, "RequestAudioDeviceConnectionRejection"},
{23, nullptr, "CancelAudioDeviceConnectionRejection"}
{22, &IBtmSystemCore::RequestAudioDeviceConnectionRejection, "RequestAudioDeviceConnectionRejection"},
{23, &IBtmSystemCore::CancelAudioDeviceConnectionRejection, "CancelAudioDeviceConnectionRejection"}
};
// clang-format on
RegisterHandlers(functions);
}
private:
void IsRadioEnabled(HLERequestContext& ctx) {
LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(true);
}
void StartGamepadPairing(HLERequestContext& ctx) {
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void CancelGamepadPairing(HLERequestContext& ctx) {
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void CancelAudioDeviceConnectionRejection(HLERequestContext& ctx) {
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetConnectedAudioDevices(HLERequestContext& ctx) {
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(0);
}
void RequestAudioDeviceConnectionRejection(HLERequestContext& ctx) {
LOG_WARNING(Service_BTM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
class BTM_SYS final : public ServiceFramework<BTM_SYS> {
@@ -308,7 +348,7 @@ public:
private:
void GetCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_BTM, "called");
LOG_WARNING(Service_BTM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);

View File

@@ -32,7 +32,7 @@ public:
{10200, nullptr, "SendFriendRequestForApplication"},
{10211, nullptr, "AddFacedFriendRequestForApplication"},
{10400, &IFriendService::GetBlockedUserListIds, "GetBlockedUserListIds"},
{10420, nullptr, "IsBlockedUserListCacheAvailable"},
{10420, &IFriendService::CheckBlockedUserListAvailability, "CheckBlockedUserListAvailability"},
{10421, nullptr, "EnsureBlockedUserListAvailable"},
{10500, nullptr, "GetProfileList"},
{10600, nullptr, "DeclareOpenOnlinePlaySession"},
@@ -206,6 +206,17 @@ private:
rb.Push(true);
}
void CheckBlockedUserListAvailability(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto uuid{rp.PopRaw<Common::UUID>()};
LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(true);
}
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* completion_event;

View File

@@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hid/emulated_console.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/console_six_axis.h"
#include "core/memory.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
ConsoleSixAxis::ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
console = hid_core.GetEmulatedConsole();
static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
"ConsoleSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
}
ConsoleSixAxis::~ConsoleSixAxis() = default;
void ConsoleSixAxis::OnInit() {}
void ConsoleSixAxis::OnRelease() {}
void ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
const auto motion_status = console->GetMotion();
shared_memory->sampling_number++;
shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
shared_memory->verticalization_error = motion_status.verticalization_error;
shared_memory->gyro_bias = motion_status.gyro_bias;
}
} // namespace Service::HID

View File

@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/vector_math.h"
#include "core/hle/service/hid/controllers/controller_base.h"
namespace Core::HID {
class EmulatedConsole;
} // namespace Core::HID
namespace Service::HID {
class ConsoleSixAxis final : public ControllerBase {
public:
explicit ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~ConsoleSixAxis() override;
// Called when the controller is initialized
void OnInit() override;
// When the controller is released
void OnRelease() override;
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
private:
// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
struct ConsoleSharedMemory {
u64 sampling_number{};
bool is_seven_six_axis_sensor_at_rest{};
INSERT_PADDING_BYTES(3); // padding
f32 verticalization_error{};
Common::Vec3f gyro_bias{};
INSERT_PADDING_BYTES(4); // padding
};
static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
ConsoleSharedMemory* shared_memory = nullptr;
Core::HID::EmulatedConsole* console = nullptr;
};
} // namespace Service::HID

View File

@@ -8,12 +8,17 @@ namespace Service::HID {
ControllerBase::ControllerBase(Core::HID::HIDCore& hid_core_) : hid_core(hid_core_) {}
ControllerBase::~ControllerBase() = default;
void ControllerBase::ActivateController() {
Result ControllerBase::Activate() {
if (is_activated) {
return;
return ResultSuccess;
}
is_activated = true;
OnInit();
return ResultSuccess;
}
Result ControllerBase::Activate(u64 aruid) {
return Activate();
}
void ControllerBase::DeactivateController() {

View File

@@ -4,6 +4,7 @@
#pragma once
#include "common/common_types.h"
#include "core/hle/result.h"
namespace Core::Timing {
class CoreTiming;
@@ -31,7 +32,8 @@ public:
// When the controller is requesting a motion update for the shared memory
virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {}
void ActivateController();
Result Activate();
Result Activate(u64 aruid);
void DeactivateController();

View File

@@ -13,7 +13,7 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
DebugPad::DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
"DebugPadSharedMemory is bigger than the shared memory");
@@ -22,13 +22,13 @@ Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
}
Controller_DebugPad::~Controller_DebugPad() = default;
DebugPad::~DebugPad() = default;
void Controller_DebugPad::OnInit() {}
void DebugPad::OnInit() {}
void Controller_DebugPad::OnRelease() {}
void DebugPad::OnRelease() {}
void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->debug_pad_lifo.buffer_count = 0;
shared_memory->debug_pad_lifo.buffer_tail = 0;

View File

@@ -15,10 +15,10 @@ struct AnalogStickState;
} // namespace Core::HID
namespace Service::HID {
class Controller_DebugPad final : public ControllerBase {
class DebugPad final : public ControllerBase {
public:
explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Controller_DebugPad() override;
explicit DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~DebugPad() override;
// Called when the controller is initialized
void OnInit() override;

View File

@@ -23,7 +23,7 @@ constexpr f32 Square(s32 num) {
return static_cast<f32>(num * num);
}
Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
Gesture::Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase(hid_core_) {
static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
"GestureSharedMemory is bigger than the shared memory");
@@ -31,17 +31,17 @@ Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_sh
reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
console = hid_core.GetEmulatedConsole();
}
Controller_Gesture::~Controller_Gesture() = default;
Gesture::~Gesture() = default;
void Controller_Gesture::OnInit() {
void Gesture::OnInit() {
shared_memory->gesture_lifo.buffer_count = 0;
shared_memory->gesture_lifo.buffer_tail = 0;
force_update = true;
}
void Controller_Gesture::OnRelease() {}
void Gesture::OnRelease() {}
void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->gesture_lifo.buffer_count = 0;
shared_memory->gesture_lifo.buffer_tail = 0;
@@ -64,7 +64,7 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
UpdateGestureSharedMemory(gesture, time_difference);
}
void Controller_Gesture::ReadTouchInput() {
void Gesture::ReadTouchInput() {
if (!Settings::values.touchscreen.enabled) {
fingers = {};
return;
@@ -76,8 +76,7 @@ void Controller_Gesture::ReadTouchInput() {
}
}
bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
f32 time_difference) {
bool Gesture::ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
if (force_update) {
force_update = false;
@@ -100,8 +99,7 @@ bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
return false;
}
void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
f32 time_difference) {
void Gesture::UpdateGestureSharedMemory(GestureProperties& gesture, f32 time_difference) {
GestureType type = GestureType::Idle;
GestureAttribute attributes{};
@@ -138,8 +136,8 @@ void Controller_Gesture::UpdateGestureSharedMemory(GestureProperties& gesture,
shared_memory->gesture_lifo.WriteNextEntry(next_state);
}
void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
GestureAttribute& attributes) {
void Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
GestureAttribute& attributes) {
const auto& last_entry = GetLastGestureEntry();
gesture.detection_count++;
@@ -152,8 +150,8 @@ void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& typ
}
}
void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
f32 time_difference) {
void Gesture::UpdateExistingGesture(GestureProperties& gesture, GestureType& type,
f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
// Promote to pan type if touch moved
@@ -186,9 +184,8 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Gestu
}
}
void Controller_Gesture::EndGesture(GestureProperties& gesture,
GestureProperties& last_gesture_props, GestureType& type,
GestureAttribute& attributes, f32 time_difference) {
void Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
GestureType& type, GestureAttribute& attributes, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
if (last_gesture_props.active_points != 0) {
@@ -222,9 +219,8 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture,
}
}
void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
GestureProperties& last_gesture_props, GestureType& type,
GestureAttribute& attributes) {
void Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
GestureType& type, GestureAttribute& attributes) {
type = GestureType::Tap;
gesture = last_gesture_props;
force_update = true;
@@ -236,9 +232,8 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
}
}
void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
GestureProperties& last_gesture_props, GestureType& type,
f32 time_difference) {
void Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
GestureType& type, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
next_state.delta = gesture.mid_point - last_entry.pos;
@@ -263,9 +258,8 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
}
}
void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
GestureProperties& last_gesture_props, GestureType& type,
f32 time_difference) {
void Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
GestureType& type, f32 time_difference) {
const auto& last_entry = GetLastGestureEntry();
next_state.vel_x =
static_cast<f32>(last_entry.delta.x) / (last_pan_time_difference + time_difference);
@@ -287,8 +281,8 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
force_update = true;
}
void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
GestureProperties& last_gesture_props, GestureType& type) {
void Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
GestureType& type) {
const auto& last_entry = GetLastGestureEntry();
type = GestureType::Swipe;
@@ -311,11 +305,11 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
next_state.direction = GestureDirection::Up;
}
const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
const Gesture::GestureState& Gesture::GetLastGestureEntry() const {
return shared_memory->gesture_lifo.ReadCurrentEntry().state;
}
Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
Gesture::GestureProperties Gesture::GetGestureProperties() {
GestureProperties gesture;
std::array<Core::HID::TouchFinger, MAX_POINTS> active_fingers;
const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),

View File

@@ -12,10 +12,10 @@
#include "core/hle/service/hid/ring_lifo.h"
namespace Service::HID {
class Controller_Gesture final : public ControllerBase {
class Gesture final : public ControllerBase {
public:
explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Controller_Gesture() override;
explicit Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Gesture() override;
// Called when the controller is initialized
void OnInit() override;

View File

@@ -12,7 +12,7 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
Keyboard::Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
"KeyboardSharedMemory is bigger than the shared memory");
@@ -21,13 +21,13 @@ Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_
emulated_devices = hid_core.GetEmulatedDevices();
}
Controller_Keyboard::~Controller_Keyboard() = default;
Keyboard::~Keyboard() = default;
void Controller_Keyboard::OnInit() {}
void Keyboard::OnInit() {}
void Controller_Keyboard::OnRelease() {}
void Keyboard::OnRelease() {}
void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->keyboard_lifo.buffer_count = 0;
shared_memory->keyboard_lifo.buffer_tail = 0;

View File

@@ -14,10 +14,10 @@ struct KeyboardKey;
} // namespace Core::HID
namespace Service::HID {
class Controller_Keyboard final : public ControllerBase {
class Keyboard final : public ControllerBase {
public:
explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Controller_Keyboard() override;
explicit Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Keyboard() override;
// Called when the controller is initialized
void OnInit() override;

View File

@@ -12,8 +12,7 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
Mouse::Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
"MouseSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
@@ -21,12 +20,12 @@ Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared
emulated_devices = hid_core.GetEmulatedDevices();
}
Controller_Mouse::~Controller_Mouse() = default;
Mouse::~Mouse() = default;
void Controller_Mouse::OnInit() {}
void Controller_Mouse::OnRelease() {}
void Mouse::OnInit() {}
void Mouse::OnRelease() {}
void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->mouse_lifo.buffer_count = 0;
shared_memory->mouse_lifo.buffer_tail = 0;

View File

@@ -14,10 +14,10 @@ struct AnalogStickState;
} // namespace Core::HID
namespace Service::HID {
class Controller_Mouse final : public ControllerBase {
class Mouse final : public ControllerBase {
public:
explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Controller_Mouse() override;
explicit Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Mouse() override;
// Called when the controller is initialized
void OnInit() override;

View File

@@ -18,6 +18,7 @@
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/kernel_helpers.h"
namespace Service::HID {
@@ -29,60 +30,8 @@ constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
Core::HID::NpadIdType::Handheld,
};
bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
switch (npad_id) {
case Core::HID::NpadIdType::Player1:
case Core::HID::NpadIdType::Player2:
case Core::HID::NpadIdType::Player3:
case Core::HID::NpadIdType::Player4:
case Core::HID::NpadIdType::Player5:
case Core::HID::NpadIdType::Player6:
case Core::HID::NpadIdType::Player7:
case Core::HID::NpadIdType::Player8:
case Core::HID::NpadIdType::Other:
case Core::HID::NpadIdType::Handheld:
return true;
default:
LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
return false;
}
}
Result Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
if (!npad_type) {
return VibrationInvalidStyleIndex;
}
if (!npad_id) {
return VibrationInvalidNpadId;
}
if (!device_index) {
return VibrationDeviceIndexOutOfRange;
}
return ResultSuccess;
}
Result Controller_NPad::VerifyValidSixAxisSensorHandle(
const Core::HID::SixAxisSensorHandle& device_handle) {
const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
if (!npad_id) {
return InvalidNpadId;
}
if (!device_index) {
return NpadDeviceIndexOutOfRange;
}
return ResultSuccess;
}
Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_)
NPad::NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_)
: ControllerBase{hid_core_}, service_context{service_context_} {
static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
for (std::size_t i = 0; i < controller_data.size(); ++i) {
@@ -103,7 +52,7 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_m
}
}
Controller_NPad::~Controller_NPad() {
NPad::~NPad() {
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
controller.device->DeleteCallback(controller.callback_key);
@@ -111,8 +60,7 @@ Controller_NPad::~Controller_NPad() {
OnRelease();
}
void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
std::size_t controller_idx) {
void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) {
if (type == Core::HID::ControllerTriggerType::All) {
ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
@@ -150,7 +98,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
}
}
void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
void NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
return;
@@ -344,12 +292,13 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices,
Common::Input::PollingMode::Active);
}
SignalStyleSetChangedEvent(npad_id);
WriteEmptyEntry(controller.shared_memory);
hid_core.SetLastActiveController(npad_id);
}
void Controller_NPad::OnInit() {
void NPad::OnInit() {
if (!IsControllerActivated()) {
return;
}
@@ -383,7 +332,7 @@ void Controller_NPad::OnInit() {
}
}
void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
void NPad::WriteEmptyEntry(NpadInternalState* npad) {
NPadGenericState dummy_pad_state{};
NpadGcTriggerState dummy_gc_state{};
dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
@@ -404,7 +353,7 @@ void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
}
void Controller_NPad::OnRelease() {
void NPad::OnRelease() {
is_controller_initialized = false;
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
@@ -415,7 +364,7 @@ void Controller_NPad::OnRelease() {
}
}
void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
void NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
std::scoped_lock lock{mutex};
auto& controller = GetControllerFromNpadIdType(npad_id);
const auto controller_type = controller.device->GetNpadStyleIndex();
@@ -457,12 +406,14 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
pad_entry.l_stick = stick_state.left;
}
if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft ||
controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
}
if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
if (controller_type == Core::HID::NpadStyleIndex::JoyconRight ||
controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
}
@@ -482,7 +433,7 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
}
}
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
@@ -612,134 +563,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
}
}
void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
const auto& controller_type = controller.device->GetNpadStyleIndex();
if (controller_type == Core::HID::NpadStyleIndex::None ||
!controller.device->IsConnected()) {
continue;
}
auto* npad = controller.shared_memory;
const auto& motion_state = controller.device->GetMotions();
auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
// Clear previous state
sixaxis_fullkey_state = {};
sixaxis_handheld_state = {};
sixaxis_dual_left_state = {};
sixaxis_dual_right_state = {};
sixaxis_left_lifo_state = {};
sixaxis_right_lifo_state = {};
if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
controller.sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_state.size(); ++e) {
controller.sixaxis_at_rest =
controller.sixaxis_at_rest && motion_state[e].is_at_rest;
}
}
const auto set_motion_state = [&](SixAxisSensorState& state,
const Core::HID::ControllerMotion& hid_state) {
using namespace std::literals::chrono_literals;
static constexpr SixAxisSensorState default_motion_state = {
.delta_time = std::chrono::nanoseconds(5ms).count(),
.accel = {0, 0, -1.0f},
.orientation =
{
Common::Vec3f{1.0f, 0, 0},
Common::Vec3f{0, 1.0f, 0},
Common::Vec3f{0, 0, 1.0f},
},
.attribute = {1},
};
if (!controller.sixaxis_sensor_enabled) {
state = default_motion_state;
return;
}
if (!Settings::values.motion_enabled.GetValue()) {
state = default_motion_state;
return;
}
state.attribute.is_connected.Assign(1);
state.delta_time = std::chrono::nanoseconds(5ms).count();
state.accel = hid_state.accel;
state.gyro = hid_state.gyro;
state.rotation = hid_state.rotation;
state.orientation = hid_state.orientation;
};
switch (controller_type) {
case Core::HID::NpadStyleIndex::None:
ASSERT(false);
break;
case Core::HID::NpadStyleIndex::ProController:
set_motion_state(sixaxis_fullkey_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::Handheld:
set_motion_state(sixaxis_handheld_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::JoyconDual:
set_motion_state(sixaxis_dual_left_state, motion_state[0]);
set_motion_state(sixaxis_dual_right_state, motion_state[1]);
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
break;
case Core::HID::NpadStyleIndex::Pokeball:
using namespace std::literals::chrono_literals;
set_motion_state(sixaxis_fullkey_state, motion_state[0]);
sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
break;
default:
break;
}
sixaxis_fullkey_state.sampling_number =
npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_handheld_state.sampling_number =
npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_dual_left_state.sampling_number =
npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_dual_right_state.sampling_number =
npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_left_lifo_state.sampling_number =
npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_right_lifo_state.sampling_number =
npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
// This buffer only is updated on handheld on HW
npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
} else {
// Handheld doesn't update this buffer on HW
npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
}
npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
}
}
void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
void NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
hid_core.SetSupportedStyleTag(style_set);
if (is_controller_initialized) {
@@ -750,14 +574,14 @@ void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
is_controller_initialized = true;
}
Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
Core::HID::NpadStyleTag NPad::GetSupportedStyleSet() const {
if (!is_controller_initialized) {
return {Core::HID::NpadStyleSet::None};
}
return hid_core.GetSupportedStyleTag();
}
Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
Result NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
constexpr std::size_t max_number_npad_ids = 0xa;
const auto length = data.size();
ASSERT(length > 0 && (length % sizeof(u32)) == 0);
@@ -773,17 +597,17 @@ Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
return ResultSuccess;
}
void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
void NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
const auto copy_amount = supported_npad_id_types.size() * sizeof(u32);
ASSERT(max_length <= copy_amount);
std::memcpy(data, supported_npad_id_types.data(), copy_amount);
}
std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
std::size_t NPad::GetSupportedNpadIdTypesSize() const {
return supported_npad_id_types.size();
}
void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
void NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
if (joy_hold_type != NpadJoyHoldType::Horizontal &&
joy_hold_type != NpadJoyHoldType::Vertical) {
LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}",
@@ -793,11 +617,11 @@ void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
hold_type = joy_hold_type;
}
Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
NPad::NpadJoyHoldType NPad::GetHoldType() const {
return hold_type;
}
void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
void NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) {
ASSERT_MSG(false, "Activation mode should be always None, Single or Dual");
return;
@@ -806,21 +630,20 @@ void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode a
handheld_activation_mode = activation_mode;
}
Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
NPad::NpadHandheldActivationMode NPad::GetNpadHandheldActivationMode() const {
return handheld_activation_mode;
}
void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
void NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
communication_mode = communication_mode_;
}
Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
NPad::NpadCommunicationMode NPad::GetNpadCommunicationMode() const {
return communication_mode;
}
bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
NpadJoyDeviceType npad_device_type,
NpadJoyAssignmentMode assignment_mode) {
bool NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return false;
@@ -889,9 +712,8 @@ bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID:
return true;
}
bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
std::size_t device_index,
const Core::HID::VibrationValue& vibration_value) {
bool NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
const Core::HID::VibrationValue& vibration_value) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!controller.device->IsConnected()) {
return false;
@@ -935,10 +757,9 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
return controller.device->SetVibration(device_index, vibration);
}
void Controller_NPad::VibrateController(
const Core::HID::VibrationDeviceHandle& vibration_device_handle,
const Core::HID::VibrationValue& vibration_value) {
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
void NPad::VibrateController(const Core::HID::VibrationDeviceHandle& vibration_device_handle,
const Core::HID::VibrationValue& vibration_value) {
if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return;
}
@@ -982,7 +803,7 @@ void Controller_NPad::VibrateController(
}
}
void Controller_NPad::VibrateControllers(
void NPad::VibrateControllers(
std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
std::span<const Core::HID::VibrationValue> vibration_values) {
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
@@ -999,9 +820,9 @@ void Controller_NPad::VibrateControllers(
}
}
Core::HID::VibrationValue Controller_NPad::GetLastVibration(
Core::HID::VibrationValue NPad::GetLastVibration(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return {};
}
@@ -1010,9 +831,9 @@ Core::HID::VibrationValue Controller_NPad::GetLastVibration(
return controller.vibration[device_index].latest_vibration_value;
}
void Controller_NPad::InitializeVibrationDevice(
void NPad::InitializeVibrationDevice(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return;
}
@@ -1021,8 +842,8 @@ void Controller_NPad::InitializeVibrationDevice(
InitializeVibrationDeviceAtIndex(npad_index, device_index);
}
void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
std::size_t device_index) {
void NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
std::size_t device_index) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!Settings::values.vibration_enabled.GetValue()) {
controller.vibration[device_index].device_mounted = false;
@@ -1033,13 +854,13 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npa
controller.device->IsVibrationEnabled(device_index);
}
void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
void NPad::SetPermitVibrationSession(bool permit_vibration_session) {
permit_vibration_session_enabled = permit_vibration_session;
}
bool Controller_NPad::IsVibrationDeviceMounted(
bool NPad::IsVibrationDeviceMounted(
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
return false;
}
@@ -1048,7 +869,7 @@ bool Controller_NPad::IsVibrationDeviceMounted(
return controller.vibration[device_index].device_mounted;
}
Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
Kernel::KReadableEvent& NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
// Fallback to player 1
@@ -1060,18 +881,17 @@ Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::Npad
return controller.styleset_changed_event->GetReadableEvent();
}
void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
void NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
const auto& controller = GetControllerFromNpadIdType(npad_id);
controller.styleset_changed_event->Signal();
}
void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
Core::HID::NpadIdType npad_id) {
void NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) {
UpdateControllerAt(controller, npad_id, true);
}
void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
Core::HID::NpadIdType npad_id, bool connected) {
void NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id,
bool connected) {
auto& controller = GetControllerFromNpadIdType(npad_id);
if (!connected) {
DisconnectNpad(npad_id);
@@ -1082,7 +902,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
InitNewlyAddedController(npad_id);
}
Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
Result NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1131,54 +951,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
return ResultSuccess;
}
Result Controller_NPad::SetGyroscopeZeroDriftMode(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode drift_mode) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
auto& controller = GetControllerFromHandle(sixaxis_handle);
sixaxis.gyroscope_zero_drift_mode = drift_mode;
controller.device->SetGyroscopeZeroDriftMode(drift_mode);
return ResultSuccess;
}
Result Controller_NPad::GetGyroscopeZeroDriftMode(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
drift_mode = sixaxis.gyroscope_zero_drift_mode;
return ResultSuccess;
}
Result Controller_NPad::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_at_rest) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& controller = GetControllerFromHandle(sixaxis_handle);
is_at_rest = controller.sixaxis_at_rest;
return ResultSuccess;
}
Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
@@ -1189,65 +964,9 @@ Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
return ResultSuccess;
}
Result Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
sixaxis.unaltered_passtrough = is_enabled;
return ResultSuccess;
}
Result Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
is_enabled = sixaxis.unaltered_passtrough;
return ResultSuccess;
}
Result Controller_NPad::LoadSixAxisSensorCalibrationParameter(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
// TODO: Request this data to the controller. On error return 0xd8ca
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
calibration = sixaxis.calibration;
return ResultSuccess;
}
Result Controller_NPad::GetSixAxisSensorIcInformation(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorIcInformation& ic_information) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
// TODO: Request this data to the controller. On error return 0xd8ca
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
ic_information = sixaxis.ic_information;
return ResultSuccess;
}
Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
@@ -1259,83 +978,32 @@ Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
return ResultSuccess;
}
Result Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool sixaxis_status) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
controller.sixaxis_sensor_enabled = sixaxis_status;
return ResultSuccess;
NPad::SixAxisLifo& NPad::GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_fullkey_lifo;
}
Result Controller_NPad::IsSixAxisSensorFusionEnabled(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
is_fusion_enabled = sixaxis.is_fusion_enabled;
return ResultSuccess;
}
Result Controller_NPad::SetSixAxisFusionEnabled(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
sixaxis.is_fusion_enabled = is_fusion_enabled;
return ResultSuccess;
NPad::SixAxisLifo& NPad::GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_handheld_lifo;
}
Result Controller_NPad::SetSixAxisFusionParameters(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto param1 = sixaxis_fusion_parameters.parameter1;
if (param1 < 0.0f || param1 > 1.0f) {
return InvalidSixAxisFusionRange;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
sixaxis.fusion = sixaxis_fusion_parameters;
return ResultSuccess;
NPad::SixAxisLifo& NPad::GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_left_lifo;
}
Result Controller_NPad::GetSixAxisFusionParameters(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters& parameters) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
parameters = sixaxis.fusion;
return ResultSuccess;
NPad::SixAxisLifo& NPad::GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_dual_right_lifo;
}
Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
Core::HID::NpadIdType npad_id_2) {
NPad::SixAxisLifo& NPad::GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_left_lifo;
}
NPad::SixAxisLifo& NPad::GetSixAxisRightLifo(Core::HID::NpadIdType npad_id) {
return GetControllerFromNpadIdType(npad_id).shared_memory->sixaxis_right_lifo;
}
Result NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
Core::HID::NpadIdType npad_id_2) {
if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2);
@@ -1397,18 +1065,17 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
return ResultSuccess;
}
void Controller_NPad::StartLRAssignmentMode() {
void NPad::StartLRAssignmentMode() {
// Nothing internally is used for lr assignment mode. Since we have the ability to set the
// controller types from boot, it doesn't really matter about showing a selection screen
is_in_lr_assignment_mode = true;
}
void Controller_NPad::StopLRAssignmentMode() {
void NPad::StopLRAssignmentMode() {
is_in_lr_assignment_mode = false;
}
Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
Core::HID::NpadIdType npad_id_2) {
Result NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) {
if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2);
@@ -1439,8 +1106,7 @@ Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
return ResultSuccess;
}
Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
Core::HID::LedPattern& pattern) const {
Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1450,8 +1116,8 @@ Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
return ResultSuccess;
}
Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
bool& is_valid) const {
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
bool& is_valid) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1461,8 +1127,8 @@ Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::
return ResultSuccess;
}
Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
bool is_protection_enabled, Core::HID::NpadIdType npad_id) {
Result NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
return InvalidNpadId;
@@ -1472,11 +1138,11 @@ Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
return ResultSuccess;
}
void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
void NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
analog_stick_use_center_clamp = use_center_clamp;
}
void Controller_NPad::ClearAllConnectedControllers() {
void NPad::ClearAllConnectedControllers() {
for (auto& controller : controller_data) {
if (controller.device->IsConnected() &&
controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
@@ -1486,13 +1152,13 @@ void Controller_NPad::ClearAllConnectedControllers() {
}
}
void Controller_NPad::DisconnectAllConnectedControllers() {
void NPad::DisconnectAllConnectedControllers() {
for (auto& controller : controller_data) {
controller.device->Disconnect();
}
}
void Controller_NPad::ConnectAllDisconnectedControllers() {
void NPad::ConnectAllDisconnectedControllers() {
for (auto& controller : controller_data) {
if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
!controller.device->IsConnected()) {
@@ -1501,18 +1167,18 @@ void Controller_NPad::ConnectAllDisconnectedControllers() {
}
}
void Controller_NPad::ClearAllControllers() {
void NPad::ClearAllControllers() {
for (auto& controller : controller_data) {
controller.device->Disconnect();
controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
}
}
Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
Core::HID::NpadButton NPad::GetAndResetPressState() {
return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
}
void Controller_NPad::ApplyNpadSystemCommonPolicy() {
void NPad::ApplyNpadSystemCommonPolicy() {
Core::HID::NpadStyleTag styletag{};
styletag.fullkey.Assign(1);
styletag.handheld.Assign(1);
@@ -1537,7 +1203,7 @@ void Controller_NPad::ApplyNpadSystemCommonPolicy() {
supported_npad_id_types[9] = Core::HID::NpadIdType::Handheld;
}
bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
bool NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
if (controller == Core::HID::NpadStyleIndex::Handheld) {
const bool support_handheld =
std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
@@ -1588,51 +1254,50 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
return false;
}
Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
NPad::NpadControllerData& NPad::GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
const NPad::NpadControllerData& NPad::GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
Core::HID::NpadIdType npad_id) {
NPad::NpadControllerData& NPad::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
const NPad::NpadControllerData& NPad::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
const auto npad_index = NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(
Core::HID::NpadIdType npad_id) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
const auto npad_index = NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
@@ -1655,7 +1320,7 @@ Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
}
}
const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
const auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
@@ -1678,50 +1343,13 @@ const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
}
}
Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.sixaxis_fullkey;
case Core::HID::NpadStyleIndex::Handheld:
return controller.sixaxis_handheld;
case Core::HID::NpadStyleIndex::JoyconDual:
if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
return controller.sixaxis_dual_left;
}
return controller.sixaxis_dual_right;
case Core::HID::NpadStyleIndex::JoyconLeft:
return controller.sixaxis_left;
case Core::HID::NpadStyleIndex::JoyconRight:
return controller.sixaxis_right;
default:
return controller.sixaxis_unknown;
}
}
NPad::AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
const auto& shared_memory = GetControllerFromNpadIdType(npad_id).shared_memory;
const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
const auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.sixaxis_fullkey;
case Core::HID::NpadStyleIndex::Handheld:
return controller.sixaxis_handheld;
case Core::HID::NpadStyleIndex::JoyconDual:
if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
return controller.sixaxis_dual_left;
}
return controller.sixaxis_dual_right;
case Core::HID::NpadStyleIndex::JoyconLeft:
return controller.sixaxis_left;
case Core::HID::NpadStyleIndex::JoyconRight:
return controller.sixaxis_right;
default:
return controller.sixaxis_unknown;
}
return {
.ui_variant = 0,
.footer = shared_memory->applet_footer_type,
};
}
} // namespace Service::HID

View File

@@ -10,7 +10,6 @@
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/vector_math.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
@@ -34,11 +33,11 @@ union Result;
namespace Service::HID {
class Controller_NPad final : public ControllerBase {
class NPad final : public ControllerBase {
public:
explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_);
~Controller_NPad() override;
explicit NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_);
~NPad() override;
// Called when the controller is initialized
void OnInit() override;
@@ -49,9 +48,6 @@ public:
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
// When the controller is requesting a motion update for the shared memory
void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
// This is nn::hid::NpadJoyHoldType
enum class NpadJoyHoldType : u64 {
Vertical = 0,
@@ -78,6 +74,46 @@ public:
MaxActivationMode = 3,
};
// This is nn::hid::system::AppletFooterUiAttributesSet
struct AppletFooterUiAttributes {
INSERT_PADDING_BYTES(0x4);
};
// This is nn::hid::system::AppletFooterUiType
enum class AppletFooterUiType : u8 {
None = 0,
HandheldNone = 1,
HandheldJoyConLeftOnly = 2,
HandheldJoyConRightOnly = 3,
HandheldJoyConLeftJoyConRight = 4,
JoyDual = 5,
JoyDualLeftOnly = 6,
JoyDualRightOnly = 7,
JoyLeftHorizontal = 8,
JoyLeftVertical = 9,
JoyRightHorizontal = 10,
JoyRightVertical = 11,
SwitchProController = 12,
CompatibleProController = 13,
CompatibleJoyCon = 14,
LarkHvc1 = 15,
LarkHvc2 = 16,
LarkNesLeft = 17,
LarkNesRight = 18,
Lucia = 19,
Verification = 20,
Lagon = 21,
};
using AppletFooterUiVariant = u8;
// This is "nn::hid::system::AppletDetailedUiType".
struct AppletDetailedUiType {
AppletFooterUiVariant ui_variant;
INSERT_PADDING_BYTES(0x2);
AppletFooterUiType footer;
};
static_assert(sizeof(AppletDetailedUiType) == 0x4, "AppletDetailedUiType is an invalid size");
// This is nn::hid::NpadCommunicationMode
enum class NpadCommunicationMode : u64 {
Mode_5ms = 0,
@@ -86,6 +122,15 @@ public:
Default = 3,
};
enum class NpadRevision : u32 {
Revision0 = 0,
Revision1 = 1,
Revision2 = 2,
Revision3 = 3,
};
using SixAxisLifo = Lifo<Core::HID::SixAxisSensorState, hid_entry_count>;
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
@@ -138,37 +183,18 @@ public:
Result DisconnectNpad(Core::HID::NpadIdType npad_id);
Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode drift_mode);
Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_at_rest) const;
Result IsFirmwareUpdateAvailableForSixAxisSensor(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
Result EnableSixAxisSensorUnalteredPassthrough(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
Result IsSixAxisSensorUnalteredPassthroughEnabled(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
Result LoadSixAxisSensorCalibrationParameter(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
Result GetSixAxisSensorIcInformation(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorIcInformation& ic_information) const;
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
const Core::HID::SixAxisSensorHandle& sixaxis_handle);
Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool sixaxis_status);
Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_fusion_enabled) const;
Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool is_fusion_enabled);
Result SetSixAxisFusionParameters(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters& parameters) const;
SixAxisLifo& GetSixAxisFullkeyLifo(Core::HID::NpadIdType npad_id);
SixAxisLifo& GetSixAxisHandheldLifo(Core::HID::NpadIdType npad_id);
SixAxisLifo& GetSixAxisDualLeftLifo(Core::HID::NpadIdType npad_id);
SixAxisLifo& GetSixAxisDualRightLifo(Core::HID::NpadIdType npad_id);
SixAxisLifo& GetSixAxisLeftLifo(Core::HID::NpadIdType npad_id);
SixAxisLifo& GetSixAxisRightLifo(Core::HID::NpadIdType npad_id);
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
bool& is_enabled) const;
@@ -192,10 +218,7 @@ public:
void ApplyNpadSystemCommonPolicy();
static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
static Result IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
static Result VerifyValidSixAxisSensorHandle(
const Core::HID::SixAxisSensorHandle& device_handle);
AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
private:
static constexpr std::size_t NPAD_COUNT = 10;
@@ -254,29 +277,6 @@ private:
};
static_assert(sizeof(NPadGenericState) == 0x28, "NPadGenericState is an invalid size");
// This is nn::hid::SixAxisSensorAttribute
struct SixAxisSensorAttribute {
union {
u32 raw{};
BitField<0, 1, u32> is_connected;
BitField<1, 1, u32> is_interpolated;
};
};
static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an invalid size");
// This is nn::hid::SixAxisSensorState
struct SixAxisSensorState {
s64 delta_time{};
s64 sampling_number{};
Common::Vec3f accel{};
Common::Vec3f gyro{};
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
SixAxisSensorAttribute attribute{};
INSERT_PADDING_BYTES(4); // Reserved
};
static_assert(sizeof(SixAxisSensorState) == 0x60, "SixAxisSensorState is an invalid size");
// This is nn::hid::server::NpadGcTriggerState
struct NpadGcTriggerState {
s64 sampling_number{};
@@ -353,37 +353,6 @@ private:
static_assert(sizeof(NfcXcdDeviceHandleStateImpl) == 0x18,
"NfcXcdDeviceHandleStateImpl is an invalid size");
// This is nn::hid::system::AppletFooterUiAttributesSet
struct AppletFooterUiAttributes {
INSERT_PADDING_BYTES(0x4);
};
// This is nn::hid::system::AppletFooterUiType
enum class AppletFooterUiType : u8 {
None = 0,
HandheldNone = 1,
HandheldJoyConLeftOnly = 2,
HandheldJoyConRightOnly = 3,
HandheldJoyConLeftJoyConRight = 4,
JoyDual = 5,
JoyDualLeftOnly = 6,
JoyDualRightOnly = 7,
JoyLeftHorizontal = 8,
JoyLeftVertical = 9,
JoyRightHorizontal = 10,
JoyRightVertical = 11,
SwitchProController = 12,
CompatibleProController = 13,
CompatibleJoyCon = 14,
LarkHvc1 = 15,
LarkHvc2 = 16,
LarkNesLeft = 17,
LarkNesRight = 18,
Lucia = 19,
Verification = 20,
Lagon = 21,
};
// This is nn::hid::NpadLarkType
enum class NpadLarkType : u32 {
Invalid,
@@ -427,12 +396,12 @@ private:
Lifo<NPadGenericState, hid_entry_count> joy_right_lifo{};
Lifo<NPadGenericState, hid_entry_count> palma_lifo{};
Lifo<NPadGenericState, hid_entry_count> system_ext_lifo{};
Lifo<SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
Lifo<SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
Lifo<SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
Lifo<SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
Lifo<SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_fullkey_lifo{};
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_handheld_lifo{};
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_left_lifo{};
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_dual_right_lifo{};
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_left_lifo{};
Lifo<Core::HID::SixAxisSensorState, hid_entry_count> sixaxis_right_lifo{};
DeviceType device_type{};
INSERT_PADDING_BYTES(0x4); // Reserved
NPadSystemProperties system_properties{};
@@ -466,16 +435,6 @@ private:
std::chrono::steady_clock::time_point last_vibration_timepoint{};
};
struct SixaxisParameters {
bool is_fusion_enabled{true};
bool unaltered_passtrough{false};
Core::HID::SixAxisSensorFusionParameters fusion{};
Core::HID::SixAxisSensorCalibrationParameter calibration{};
Core::HID::SixAxisSensorIcInformation ic_information{};
Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
Core::HID::GyroscopeZeroDriftMode::Standard};
};
struct NpadControllerData {
Kernel::KEvent* styleset_changed_event{};
NpadInternalState* shared_memory = nullptr;
@@ -489,27 +448,10 @@ private:
bool is_dual_left_connected{true};
bool is_dual_right_connected{true};
// Motion parameters
bool sixaxis_at_rest{true};
bool sixaxis_sensor_enabled{true};
SixaxisParameters sixaxis_fullkey{};
SixaxisParameters sixaxis_handheld{};
SixaxisParameters sixaxis_dual_left{};
SixaxisParameters sixaxis_dual_right{};
SixaxisParameters sixaxis_left{};
SixaxisParameters sixaxis_right{};
SixaxisParameters sixaxis_unknown{};
// Current pad state
NPadGenericState npad_pad_state{};
NPadGenericState npad_libnx_state{};
NpadGcTriggerState npad_trigger_state{};
SixAxisSensorState sixaxis_fullkey_state{};
SixAxisSensorState sixaxis_handheld_state{};
SixAxisSensorState sixaxis_dual_left_state{};
SixAxisSensorState sixaxis_dual_right_state{};
SixAxisSensorState sixaxis_left_lifo_state{};
SixAxisSensorState sixaxis_right_lifo_state{};
int callback_key{};
};
@@ -519,14 +461,14 @@ private:
void RequestPadStateUpdate(Core::HID::NpadIdType npad_id);
void WriteEmptyEntry(NpadInternalState* npad);
NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const;
NpadControllerData& GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::VibrationDeviceHandle& device_handle) const;
NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const;
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
@@ -534,9 +476,6 @@ private:
const Core::HID::SixAxisSensorHandle& device_handle);
const Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
const Core::HID::SixAxisSensorHandle& device_handle) const;
SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
const SixaxisParameters& GetSixaxisState(
const Core::HID::SixAxisSensorHandle& device_handle) const;
std::atomic<u64> press_state{};

View File

@@ -12,43 +12,43 @@
namespace Service::HID {
Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_)
Palma::Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_)
: ControllerBase{hid_core_}, service_context{service_context_} {
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
}
Controller_Palma::~Controller_Palma() {
Palma::~Palma() {
service_context.CloseEvent(operation_complete_event);
};
void Controller_Palma::OnInit() {}
void Palma::OnInit() {}
void Controller_Palma::OnRelease() {}
void Palma::OnRelease() {}
void Controller_Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void Palma::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
}
Result Controller_Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id,
PalmaConnectionHandle& handle) {
Result Palma::GetPalmaConnectionHandle(Core::HID::NpadIdType npad_id,
PalmaConnectionHandle& handle) {
active_handle.npad_id = npad_id;
handle = active_handle;
return ResultSuccess;
}
Result Controller_Palma::InitializePalma(const PalmaConnectionHandle& handle) {
Result Palma::InitializePalma(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
ActivateController();
Activate();
return ResultSuccess;
}
Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent(
Kernel::KReadableEvent& Palma::AcquirePalmaOperationCompleteEvent(
const PalmaConnectionHandle& handle) const {
if (handle.npad_id != active_handle.npad_id) {
LOG_ERROR(Service_HID, "Invalid npad id {}", handle.npad_id);
@@ -56,9 +56,9 @@ Kernel::KReadableEvent& Controller_Palma::AcquirePalmaOperationCompleteEvent(
return operation_complete_event->GetReadableEvent();
}
Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle,
PalmaOperationType& operation_type,
PalmaOperationData& data) const {
Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle,
PalmaOperationType& operation_type,
PalmaOperationData& data) const {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -67,8 +67,7 @@ Result Controller_Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& hand
return ResultSuccess;
}
Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle,
u64 palma_activity) {
Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_activity) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -79,8 +78,7 @@ Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle,
return ResultSuccess;
}
Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle,
PalmaFrModeType fr_mode_) {
Result Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle, PalmaFrModeType fr_mode_) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -88,7 +86,7 @@ Result Controller_Palma::SetPalmaFrModeType(const PalmaConnectionHandle& handle,
return ResultSuccess;
}
Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -99,25 +97,25 @@ Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) {
return ResultSuccess;
}
Result Controller_Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) {
Result Palma::EnablePalmaStep(const PalmaConnectionHandle& handle, bool is_enabled) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
return ResultSuccess;
}
Result Controller_Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) {
Result Palma::ResetPalmaStep(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
return ResultSuccess;
}
void Controller_Palma::ReadPalmaApplicationSection() {}
void Palma::ReadPalmaApplicationSection() {}
void Controller_Palma::WritePalmaApplicationSection() {}
void Palma::WritePalmaApplicationSection() {}
Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) {
Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -128,7 +126,7 @@ Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle
return ResultSuccess;
}
Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) {
Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -139,10 +137,9 @@ Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle&
return ResultSuccess;
}
void Controller_Palma::WritePalmaActivityEntry() {}
void Palma::WritePalmaActivityEntry() {}
Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle,
u64 unknown) {
Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, u64 unknown) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -153,8 +150,8 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl
return ResultSuccess;
}
Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
Common::ProcessAddress t_mem, u64 size) {
Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWaveSet wave,
Common::ProcessAddress t_mem, u64 size) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -165,8 +162,8 @@ Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle
return ResultSuccess;
}
Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
s32 database_id_version_) {
Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle,
s32 database_id_version_) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -178,8 +175,7 @@ Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnec
return ResultSuccess;
}
Result Controller_Palma::GetPalmaDataBaseIdentificationVersion(
const PalmaConnectionHandle& handle) {
Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -191,26 +187,26 @@ Result Controller_Palma::GetPalmaDataBaseIdentificationVersion(
return ResultSuccess;
}
void Controller_Palma::SuspendPalmaFeature() {}
void Palma::SuspendPalmaFeature() {}
Result Controller_Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const {
Result Palma::GetPalmaOperationResult(const PalmaConnectionHandle& handle) const {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
return operation.result;
}
void Controller_Palma::ReadPalmaPlayLog() {}
void Palma::ReadPalmaPlayLog() {}
void Controller_Palma::ResetPalmaPlayLog() {}
void Palma::ResetPalmaPlayLog() {}
void Controller_Palma::SetIsPalmaAllConnectable(bool is_all_connectable) {
void Palma::SetIsPalmaAllConnectable(bool is_all_connectable) {
// If true controllers are able to be paired
is_connectable = is_all_connectable;
}
void Controller_Palma::SetIsPalmaPairedConnectable() {}
void Palma::SetIsPalmaPairedConnectable() {}
Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) {
Result Palma::PairPalma(const PalmaConnectionHandle& handle) {
if (handle.npad_id != active_handle.npad_id) {
return InvalidPalmaHandle;
}
@@ -218,14 +214,14 @@ Result Controller_Palma::PairPalma(const PalmaConnectionHandle& handle) {
return ResultSuccess;
}
void Controller_Palma::SetPalmaBoostMode(bool boost_mode) {}
void Palma::SetPalmaBoostMode(bool boost_mode) {}
void Controller_Palma::CancelWritePalmaWaveEntry() {}
void Palma::CancelWritePalmaWaveEntry() {}
void Controller_Palma::EnablePalmaBoostMode() {}
void Palma::EnablePalmaBoostMode() {}
void Controller_Palma::GetPalmaBluetoothAddress() {}
void Palma::GetPalmaBluetoothAddress() {}
void Controller_Palma::SetDisallowedPalmaConnection() {}
void Palma::SetDisallowedPalmaConnection() {}
} // namespace Service::HID

View File

@@ -23,7 +23,7 @@ class EmulatedController;
} // namespace Core::HID
namespace Service::HID {
class Controller_Palma final : public ControllerBase {
class Palma final : public ControllerBase {
public:
using PalmaOperationData = std::array<u8, 0x140>;
@@ -97,9 +97,9 @@ public:
static_assert(sizeof(PalmaConnectionHandle) == 0x8,
"PalmaConnectionHandle has incorrect size.");
explicit Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_);
~Controller_Palma() override;
explicit Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
KernelHelpers::ServiceContext& service_context_);
~Palma() override;
// Called when the controller is initialized
void OnInit() override;

View File

@@ -1,32 +1,29 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <cstring>
#include "common/common_types.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/hid/emulated_console.h"
#include "core/hid/emulated_devices.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/console_sixaxis.h"
#include "core/hle/service/hid/controllers/seven_six_axis.h"
#include "core/memory.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_)
SevenSixAxis::SevenSixAxis(Core::System& system_)
: ControllerBase{system_.HIDCore()}, system{system_} {
console = hid_core.GetEmulatedConsole();
static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
"ConsoleSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
}
Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
SevenSixAxis::~SevenSixAxis() = default;
void Controller_ConsoleSixAxis::OnInit() {}
void SevenSixAxis::OnInit() {}
void SevenSixAxis::OnRelease() {}
void Controller_ConsoleSixAxis::OnRelease() {}
void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated() || transfer_memory == 0) {
seven_sixaxis_lifo.buffer_count = 0;
seven_sixaxis_lifo.buffer_tail = 0;
@@ -53,22 +50,17 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
-motion_status.quaternion.xyz.z,
};
shared_memory->sampling_number++;
shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
shared_memory->verticalization_error = motion_status.verticalization_error;
shared_memory->gyro_bias = motion_status.gyro_bias;
// Update seven six axis transfer memory
seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
sizeof(seven_sixaxis_lifo));
}
void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
void SevenSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
transfer_memory = t_mem;
}
void Controller_ConsoleSixAxis::ResetTimestamp() {
void SevenSixAxis::ResetTimestamp() {
last_saved_timestamp = last_global_timestamp;
}
} // namespace Service::HID

View File

@@ -1,10 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
#include "common/common_types.h"
#include "common/quaternion.h"
#include "common/typed_address.h"
#include "core/hle/service/hid/controllers/controller_base.h"
@@ -19,10 +18,10 @@ class EmulatedConsole;
} // namespace Core::HID
namespace Service::HID {
class Controller_ConsoleSixAxis final : public ControllerBase {
class SevenSixAxis final : public ControllerBase {
public:
explicit Controller_ConsoleSixAxis(Core::System& system_, u8* raw_shared_memory_);
~Controller_ConsoleSixAxis() override;
explicit SevenSixAxis(Core::System& system_);
~SevenSixAxis() override;
// Called when the controller is initialized
void OnInit() override;
@@ -51,28 +50,16 @@ private:
};
static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size");
// This is nn::hid::detail::ConsoleSixAxisSensorSharedMemoryFormat
struct ConsoleSharedMemory {
u64 sampling_number{};
bool is_seven_six_axis_sensor_at_rest{};
INSERT_PADDING_BYTES(3); // padding
f32 verticalization_error{};
Common::Vec3f gyro_bias{};
INSERT_PADDING_BYTES(4); // padding
};
static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
SevenSixAxisState next_seven_sixaxis_state{};
Common::ProcessAddress transfer_memory{};
ConsoleSharedMemory* shared_memory = nullptr;
Core::HID::EmulatedConsole* console = nullptr;
u64 last_saved_timestamp{};
u64 last_global_timestamp{};
SevenSixAxisState next_seven_sixaxis_state{};
Common::ProcessAddress transfer_memory{};
Core::HID::EmulatedConsole* console = nullptr;
Core::System& system;
};
} // namespace Service::HID

View File

@@ -0,0 +1,413 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common/common_types.h"
#include "core/core_timing.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_util.h"
namespace Service::HID {
SixAxis::SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_)
: ControllerBase{hid_core_}, npad{npad_} {
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
controller.device = hid_core.GetEmulatedControllerByIndex(i);
}
}
SixAxis::~SixAxis() = default;
void SixAxis::OnInit() {}
void SixAxis::OnRelease() {}
void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
return;
}
for (std::size_t i = 0; i < controller_data.size(); ++i) {
auto& controller = controller_data[i];
const auto npad_id = IndexToNpadIdType(i);
const auto& controller_type = controller.device->GetNpadStyleIndex();
if (controller_type == Core::HID::NpadStyleIndex::None ||
!controller.device->IsConnected()) {
continue;
}
const auto& motion_state = controller.device->GetMotions();
auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
auto& sixaxis_fullkey_lifo = npad->GetSixAxisFullkeyLifo(npad_id);
auto& sixaxis_handheld_lifo = npad->GetSixAxisHandheldLifo(npad_id);
auto& sixaxis_dual_left_lifo = npad->GetSixAxisDualLeftLifo(npad_id);
auto& sixaxis_dual_right_lifo = npad->GetSixAxisDualRightLifo(npad_id);
auto& sixaxis_left_lifo = npad->GetSixAxisLeftLifo(npad_id);
auto& sixaxis_right_lifo = npad->GetSixAxisRightLifo(npad_id);
// Clear previous state
sixaxis_fullkey_state = {};
sixaxis_handheld_state = {};
sixaxis_dual_left_state = {};
sixaxis_dual_right_state = {};
sixaxis_left_lifo_state = {};
sixaxis_right_lifo_state = {};
if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
controller.sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_state.size(); ++e) {
controller.sixaxis_at_rest =
controller.sixaxis_at_rest && motion_state[e].is_at_rest;
}
}
const auto set_motion_state = [&](Core::HID::SixAxisSensorState& state,
const Core::HID::ControllerMotion& hid_state) {
using namespace std::literals::chrono_literals;
static constexpr Core::HID::SixAxisSensorState default_motion_state = {
.delta_time = std::chrono::nanoseconds(5ms).count(),
.accel = {0, 0, -1.0f},
.orientation =
{
Common::Vec3f{1.0f, 0, 0},
Common::Vec3f{0, 1.0f, 0},
Common::Vec3f{0, 0, 1.0f},
},
.attribute = {1},
};
if (!controller.sixaxis_sensor_enabled) {
state = default_motion_state;
return;
}
if (!Settings::values.motion_enabled.GetValue()) {
state = default_motion_state;
return;
}
state.attribute.is_connected.Assign(1);
state.delta_time = std::chrono::nanoseconds(5ms).count();
state.accel = hid_state.accel;
state.gyro = hid_state.gyro;
state.rotation = hid_state.rotation;
state.orientation = hid_state.orientation;
};
switch (controller_type) {
case Core::HID::NpadStyleIndex::None:
ASSERT(false);
break;
case Core::HID::NpadStyleIndex::ProController:
set_motion_state(sixaxis_fullkey_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::Handheld:
set_motion_state(sixaxis_handheld_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::JoyconDual:
set_motion_state(sixaxis_dual_left_state, motion_state[0]);
set_motion_state(sixaxis_dual_right_state, motion_state[1]);
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
break;
case Core::HID::NpadStyleIndex::Pokeball:
using namespace std::literals::chrono_literals;
set_motion_state(sixaxis_fullkey_state, motion_state[0]);
sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
break;
default:
break;
}
sixaxis_fullkey_state.sampling_number =
sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_handheld_state.sampling_number =
sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_dual_left_state.sampling_number =
sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_dual_right_state.sampling_number =
sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_left_lifo_state.sampling_number =
sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
sixaxis_right_lifo_state.sampling_number =
sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
if (IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
// This buffer only is updated on handheld on HW
sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
} else {
// Handheld doesn't update this buffer on HW
sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
}
sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
}
}
Result SixAxis::SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode drift_mode) {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
auto& controller = GetControllerFromHandle(sixaxis_handle);
sixaxis.gyroscope_zero_drift_mode = drift_mode;
controller.device->SetGyroscopeZeroDriftMode(drift_mode);
return ResultSuccess;
}
Result SixAxis::GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
drift_mode = sixaxis.gyroscope_zero_drift_mode;
return ResultSuccess;
}
Result SixAxis::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_at_rest) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& controller = GetControllerFromHandle(sixaxis_handle);
is_at_rest = controller.sixaxis_at_rest;
return ResultSuccess;
}
Result SixAxis::LoadSixAxisSensorCalibrationParameter(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
// TODO: Request this data to the controller. On error return 0xd8ca
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
calibration = sixaxis.calibration;
return ResultSuccess;
}
Result SixAxis::GetSixAxisSensorIcInformation(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorIcInformation& ic_information) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
// TODO: Request this data to the controller. On error return 0xd8ca
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
ic_information = sixaxis.ic_information;
return ResultSuccess;
}
Result SixAxis::EnableSixAxisSensorUnalteredPassthrough(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
sixaxis.unaltered_passtrough = is_enabled;
return ResultSuccess;
}
Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
is_enabled = sixaxis.unaltered_passtrough;
return ResultSuccess;
}
Result SixAxis::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool sixaxis_status) {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& controller = GetControllerFromHandle(sixaxis_handle);
controller.sixaxis_sensor_enabled = sixaxis_status;
return ResultSuccess;
}
Result SixAxis::IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_fusion_enabled) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
is_fusion_enabled = sixaxis.is_fusion_enabled;
return ResultSuccess;
}
Result SixAxis::SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool is_fusion_enabled) {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
sixaxis.is_fusion_enabled = is_fusion_enabled;
return ResultSuccess;
}
Result SixAxis::SetSixAxisFusionParameters(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto param1 = sixaxis_fusion_parameters.parameter1;
if (param1 < 0.0f || param1 > 1.0f) {
return InvalidSixAxisFusionRange;
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
sixaxis.fusion = sixaxis_fusion_parameters;
return ResultSuccess;
}
Result SixAxis::GetSixAxisFusionParameters(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters& parameters) const {
const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
return is_valid;
}
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
parameters = sixaxis.fusion;
return ResultSuccess;
}
SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.sixaxis_fullkey;
case Core::HID::NpadStyleIndex::Handheld:
return controller.sixaxis_handheld;
case Core::HID::NpadStyleIndex::JoyconDual:
if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
return controller.sixaxis_dual_left;
}
return controller.sixaxis_dual_right;
case Core::HID::NpadStyleIndex::JoyconLeft:
return controller.sixaxis_left;
case Core::HID::NpadStyleIndex::JoyconRight:
return controller.sixaxis_right;
default:
return controller.sixaxis_unknown;
}
}
const SixAxis::SixaxisParameters& SixAxis::GetSixaxisState(
const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
const auto& controller = GetControllerFromHandle(sixaxis_handle);
switch (sixaxis_handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Pokeball:
return controller.sixaxis_fullkey;
case Core::HID::NpadStyleIndex::Handheld:
return controller.sixaxis_handheld;
case Core::HID::NpadStyleIndex::JoyconDual:
if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
return controller.sixaxis_dual_left;
}
return controller.sixaxis_dual_right;
case Core::HID::NpadStyleIndex::JoyconLeft:
return controller.sixaxis_left;
case Core::HID::NpadStyleIndex::JoyconRight:
return controller.sixaxis_right;
default:
return controller.sixaxis_unknown;
}
}
SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
const SixAxis::NpadControllerData& SixAxis::GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const {
const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
return GetControllerFromNpadIdType(npad_id);
}
SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
const auto npad_index = NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
const SixAxis::NpadControllerData& SixAxis::GetControllerFromNpadIdType(
Core::HID::NpadIdType npad_id) const {
if (!IsNpadIdValid(npad_id)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
npad_id = Core::HID::NpadIdType::Player1;
}
const auto npad_index = NpadIdTypeToIndex(npad_id);
return controller_data[npad_index];
}
} // namespace Service::HID

View File

@@ -0,0 +1,111 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/ring_lifo.h"
namespace Core::HID {
class EmulatedController;
} // namespace Core::HID
namespace Service::HID {
class NPad;
class SixAxis final : public ControllerBase {
public:
explicit SixAxis(Core::HID::HIDCore& hid_core_, std::shared_ptr<NPad> npad_);
~SixAxis() override;
// Called when the controller is initialized
void OnInit() override;
// When the controller is released
void OnRelease() override;
// When the controller is requesting an update for the shared memory
void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode drift_mode);
Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_at_rest) const;
Result EnableSixAxisSensorUnalteredPassthrough(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
Result IsSixAxisSensorUnalteredPassthroughEnabled(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
Result LoadSixAxisSensorCalibrationParameter(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
Result GetSixAxisSensorIcInformation(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorIcInformation& ic_information) const;
Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool sixaxis_status);
Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_fusion_enabled) const;
Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool is_fusion_enabled);
Result SetSixAxisFusionParameters(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::SixAxisSensorFusionParameters& parameters) const;
private:
static constexpr std::size_t NPAD_COUNT = 10;
struct SixaxisParameters {
bool is_fusion_enabled{true};
bool unaltered_passtrough{false};
Core::HID::SixAxisSensorFusionParameters fusion{};
Core::HID::SixAxisSensorCalibrationParameter calibration{};
Core::HID::SixAxisSensorIcInformation ic_information{};
Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
Core::HID::GyroscopeZeroDriftMode::Standard};
};
struct NpadControllerData {
Core::HID::EmulatedController* device = nullptr;
// Motion parameters
bool sixaxis_at_rest{true};
bool sixaxis_sensor_enabled{true};
SixaxisParameters sixaxis_fullkey{};
SixaxisParameters sixaxis_handheld{};
SixaxisParameters sixaxis_dual_left{};
SixaxisParameters sixaxis_dual_right{};
SixaxisParameters sixaxis_left{};
SixaxisParameters sixaxis_right{};
SixaxisParameters sixaxis_unknown{};
// Current pad state
Core::HID::SixAxisSensorState sixaxis_fullkey_state{};
Core::HID::SixAxisSensorState sixaxis_handheld_state{};
Core::HID::SixAxisSensorState sixaxis_dual_left_state{};
Core::HID::SixAxisSensorState sixaxis_dual_right_state{};
Core::HID::SixAxisSensorState sixaxis_left_lifo_state{};
Core::HID::SixAxisSensorState sixaxis_right_lifo_state{};
int callback_key{};
};
SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
const SixaxisParameters& GetSixaxisState(
const Core::HID::SixAxisSensorHandle& device_handle) const;
NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle);
const NpadControllerData& GetControllerFromHandle(
const Core::HID::SixAxisSensorHandle& device_handle) const;
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
std::shared_ptr<NPad> npad;
std::array<NpadControllerData, NPAD_COUNT> controller_data{};
};
} // namespace Service::HID

View File

@@ -15,8 +15,7 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
u8* raw_shared_memory_)
TouchScreen::TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
"TouchSharedMemory is bigger than the shared memory");
@@ -25,13 +24,13 @@ Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
console = hid_core.GetEmulatedConsole();
}
Controller_Touchscreen::~Controller_Touchscreen() = default;
TouchScreen::~TouchScreen() = default;
void Controller_Touchscreen::OnInit() {}
void TouchScreen::OnInit() {}
void Controller_Touchscreen::OnRelease() {}
void TouchScreen::OnRelease() {}
void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void TouchScreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
shared_memory->touch_screen_lifo.timestamp = core_timing.GetGlobalTimeNs().count();
if (!IsControllerActivated()) {

View File

@@ -14,10 +14,10 @@ class EmulatedConsole;
} // namespace Core::HID
namespace Service::HID {
class Controller_Touchscreen final : public ControllerBase {
class TouchScreen final : public ControllerBase {
public:
explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Controller_Touchscreen() override;
explicit TouchScreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~TouchScreen() override;
// Called when the controller is initialized
void OnInit() override;

View File

@@ -10,20 +10,19 @@
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
: ControllerBase{hid_core_} {
XPad::XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) : ControllerBase{hid_core_} {
static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
"XpadSharedMemory is bigger than the shared memory");
shared_memory = std::construct_at(
reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
}
Controller_XPad::~Controller_XPad() = default;
XPad::~XPad() = default;
void Controller_XPad::OnInit() {}
void XPad::OnInit() {}
void Controller_XPad::OnRelease() {}
void XPad::OnRelease() {}
void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
void XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
if (!IsControllerActivated()) {
shared_memory->basic_xpad_lifo.buffer_count = 0;
shared_memory->basic_xpad_lifo.buffer_tail = 0;

View File

@@ -10,10 +10,10 @@
#include "core/hle/service/hid/ring_lifo.h"
namespace Service::HID {
class Controller_XPad final : public ControllerBase {
class XPad final : public ControllerBase {
public:
explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~Controller_XPad() override;
explicit XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
~XPad() override;
// Called when the controller is initialized
void OnInit() override;

File diff suppressed because it is too large Load Diff

View File

@@ -3,220 +3,12 @@
#pragma once
#include <chrono>
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Core::Timing {
struct EventType;
}
namespace Service::SM {
class ServiceManager;
namespace Core {
class System;
}
namespace Service::HID {
enum class HidController : std::size_t {
DebugPad,
Touchscreen,
Mouse,
Keyboard,
XPad,
HomeButton,
SleepButton,
CaptureButton,
InputDetector,
UniquePad,
NPad,
Gesture,
ConsoleSixAxisSensor,
DebugMouse,
Palma,
MaxControllers,
};
class IAppletResource final : public ServiceFramework<IAppletResource> {
public:
explicit IAppletResource(Core::System& system_,
KernelHelpers::ServiceContext& service_context_);
~IAppletResource() override;
void ActivateController(HidController controller);
void DeactivateController(HidController controller);
template <typename T>
T& GetController(HidController controller) {
return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
}
template <typename T>
const T& GetController(HidController controller) const {
return static_cast<T&>(*controllers[static_cast<size_t>(controller)]);
}
private:
template <typename T>
void MakeController(HidController controller, u8* shared_memory) {
if constexpr (std::is_constructible_v<T, Core::System&, u8*>) {
controllers[static_cast<std::size_t>(controller)] =
std::make_unique<T>(system, shared_memory);
} else {
controllers[static_cast<std::size_t>(controller)] =
std::make_unique<T>(system.HIDCore(), shared_memory);
}
}
template <typename T>
void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
controllers[static_cast<std::size_t>(controller)] =
std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
}
void GetSharedMemoryHandle(HLERequestContext& ctx);
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
KernelHelpers::ServiceContext& service_context;
std::shared_ptr<Core::Timing::EventType> npad_update_event;
std::shared_ptr<Core::Timing::EventType> default_update_event;
std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
std::shared_ptr<Core::Timing::EventType> motion_update_event;
std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
controllers{};
};
class Hid final : public ServiceFramework<Hid> {
public:
explicit Hid(Core::System& system_, std::shared_ptr<IAppletResource> applet_resource_);
~Hid() override;
std::shared_ptr<IAppletResource> GetAppletResource();
private:
void CreateAppletResource(HLERequestContext& ctx);
void ActivateDebugPad(HLERequestContext& ctx);
void ActivateTouchScreen(HLERequestContext& ctx);
void ActivateMouse(HLERequestContext& ctx);
void ActivateKeyboard(HLERequestContext& ctx);
void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
void ActivateXpad(HLERequestContext& ctx);
void GetXpadIDs(HLERequestContext& ctx);
void ActivateSixAxisSensor(HLERequestContext& ctx);
void DeactivateSixAxisSensor(HLERequestContext& ctx);
void StartSixAxisSensor(HLERequestContext& ctx);
void StopSixAxisSensor(HLERequestContext& ctx);
void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
void EnableSixAxisSensorFusion(HLERequestContext& ctx);
void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
void IsSixAxisSensorAtRest(HLERequestContext& ctx);
void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
void ActivateGesture(HLERequestContext& ctx);
void SetSupportedNpadStyleSet(HLERequestContext& ctx);
void GetSupportedNpadStyleSet(HLERequestContext& ctx);
void SetSupportedNpadIdType(HLERequestContext& ctx);
void ActivateNpad(HLERequestContext& ctx);
void DeactivateNpad(HLERequestContext& ctx);
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
void DisconnectNpad(HLERequestContext& ctx);
void GetPlayerLedPattern(HLERequestContext& ctx);
void ActivateNpadWithRevision(HLERequestContext& ctx);
void SetNpadJoyHoldType(HLERequestContext& ctx);
void GetNpadJoyHoldType(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
void StartLrAssignmentMode(HLERequestContext& ctx);
void StopLrAssignmentMode(HLERequestContext& ctx);
void SetNpadHandheldActivationMode(HLERequestContext& ctx);
void GetNpadHandheldActivationMode(HLERequestContext& ctx);
void SwapNpadAssignment(HLERequestContext& ctx);
void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
void GetVibrationDeviceInfo(HLERequestContext& ctx);
void SendVibrationValue(HLERequestContext& ctx);
void GetActualVibrationValue(HLERequestContext& ctx);
void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
void PermitVibration(HLERequestContext& ctx);
void IsVibrationPermitted(HLERequestContext& ctx);
void SendVibrationValues(HLERequestContext& ctx);
void SendVibrationGcErmCommand(HLERequestContext& ctx);
void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
void BeginPermitVibrationSession(HLERequestContext& ctx);
void EndPermitVibrationSession(HLERequestContext& ctx);
void IsVibrationDeviceMounted(HLERequestContext& ctx);
void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
void StartConsoleSixAxisSensor(HLERequestContext& ctx);
void StopConsoleSixAxisSensor(HLERequestContext& ctx);
void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
void StartSevenSixAxisSensor(HLERequestContext& ctx);
void StopSevenSixAxisSensor(HLERequestContext& ctx);
void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
void GetPalmaConnectionHandle(HLERequestContext& ctx);
void InitializePalma(HLERequestContext& ctx);
void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
void GetPalmaOperationInfo(HLERequestContext& ctx);
void PlayPalmaActivity(HLERequestContext& ctx);
void SetPalmaFrModeType(HLERequestContext& ctx);
void ReadPalmaStep(HLERequestContext& ctx);
void EnablePalmaStep(HLERequestContext& ctx);
void ResetPalmaStep(HLERequestContext& ctx);
void ReadPalmaApplicationSection(HLERequestContext& ctx);
void WritePalmaApplicationSection(HLERequestContext& ctx);
void ReadPalmaUniqueCode(HLERequestContext& ctx);
void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
void WritePalmaActivityEntry(HLERequestContext& ctx);
void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
void WritePalmaWaveEntry(HLERequestContext& ctx);
void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
void SuspendPalmaFeature(HLERequestContext& ctx);
void GetPalmaOperationResult(HLERequestContext& ctx);
void ReadPalmaPlayLog(HLERequestContext& ctx);
void ResetPalmaPlayLog(HLERequestContext& ctx);
void SetIsPalmaAllConnectable(HLERequestContext& ctx);
void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
void PairPalma(HLERequestContext& ctx);
void SetPalmaBoostMode(HLERequestContext& ctx);
void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
void EnablePalmaBoostMode(HLERequestContext& ctx);
void GetPalmaBluetoothAddress(HLERequestContext& ctx);
void SetDisallowedPalmaConnection(HLERequestContext& ctx);
void SetNpadCommunicationMode(HLERequestContext& ctx);
void GetNpadCommunicationMode(HLERequestContext& ctx);
void SetTouchScreenConfiguration(HLERequestContext& ctx);
void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
std::shared_ptr<IAppletResource> applet_resource;
KernelHelpers::ServiceContext service_context;
};
void LoopProcess(Core::System& system);
} // namespace Service::HID

View File

@@ -0,0 +1,159 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/hid/hid_debug_server.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
namespace Service::HID {
IHidDebugServer::IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
: ServiceFramework{system_, "hid:dbg"}, resource_manager{resource} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "DeactivateDebugPad"},
{1, nullptr, "SetDebugPadAutoPilotState"},
{2, nullptr, "UnsetDebugPadAutoPilotState"},
{10, nullptr, "DeactivateTouchScreen"},
{11, nullptr, "SetTouchScreenAutoPilotState"},
{12, nullptr, "UnsetTouchScreenAutoPilotState"},
{13, nullptr, "GetTouchScreenConfiguration"},
{14, nullptr, "ProcessTouchScreenAutoTune"},
{15, nullptr, "ForceStopTouchScreenManagement"},
{16, nullptr, "ForceRestartTouchScreenManagement"},
{17, nullptr, "IsTouchScreenManaged"},
{20, nullptr, "DeactivateMouse"},
{21, nullptr, "SetMouseAutoPilotState"},
{22, nullptr, "UnsetMouseAutoPilotState"},
{25, nullptr, "SetDebugMouseAutoPilotState"},
{26, nullptr, "UnsetDebugMouseAutoPilotState"},
{30, nullptr, "DeactivateKeyboard"},
{31, nullptr, "SetKeyboardAutoPilotState"},
{32, nullptr, "UnsetKeyboardAutoPilotState"},
{50, nullptr, "DeactivateXpad"},
{51, nullptr, "SetXpadAutoPilotState"},
{52, nullptr, "UnsetXpadAutoPilotState"},
{53, nullptr, "DeactivateJoyXpad"},
{60, nullptr, "ClearNpadSystemCommonPolicy"},
{61, nullptr, "DeactivateNpad"},
{62, nullptr, "ForceDisconnectNpad"},
{91, nullptr, "DeactivateGesture"},
{110, nullptr, "DeactivateHomeButton"},
{111, nullptr, "SetHomeButtonAutoPilotState"},
{112, nullptr, "UnsetHomeButtonAutoPilotState"},
{120, nullptr, "DeactivateSleepButton"},
{121, nullptr, "SetSleepButtonAutoPilotState"},
{122, nullptr, "UnsetSleepButtonAutoPilotState"},
{123, nullptr, "DeactivateInputDetector"},
{130, nullptr, "DeactivateCaptureButton"},
{131, nullptr, "SetCaptureButtonAutoPilotState"},
{132, nullptr, "UnsetCaptureButtonAutoPilotState"},
{133, nullptr, "SetShiftAccelerometerCalibrationValue"},
{134, nullptr, "GetShiftAccelerometerCalibrationValue"},
{135, nullptr, "SetShiftGyroscopeCalibrationValue"},
{136, nullptr, "GetShiftGyroscopeCalibrationValue"},
{140, nullptr, "DeactivateConsoleSixAxisSensor"},
{141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
{142, nullptr, "DeactivateSevenSixAxisSensor"},
{143, nullptr, "GetConsoleSixAxisSensorCountStates"},
{144, nullptr, "GetAccelerometerFsr"},
{145, nullptr, "SetAccelerometerFsr"},
{146, nullptr, "GetAccelerometerOdr"},
{147, nullptr, "SetAccelerometerOdr"},
{148, nullptr, "GetGyroscopeFsr"},
{149, nullptr, "SetGyroscopeFsr"},
{150, nullptr, "GetGyroscopeOdr"},
{151, nullptr, "SetGyroscopeOdr"},
{152, nullptr, "GetWhoAmI"},
{201, nullptr, "ActivateFirmwareUpdate"},
{202, nullptr, "DeactivateFirmwareUpdate"},
{203, nullptr, "StartFirmwareUpdate"},
{204, nullptr, "GetFirmwareUpdateStage"},
{205, nullptr, "GetFirmwareVersion"},
{206, nullptr, "GetDestinationFirmwareVersion"},
{207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
{208, nullptr, "StartFirmwareUpdateForRevert"},
{209, nullptr, "GetAvailableFirmwareVersionForRevert"},
{210, nullptr, "IsFirmwareUpdatingDevice"},
{211, nullptr, "StartFirmwareUpdateIndividual"},
{215, nullptr, "SetUsbFirmwareForceUpdateEnabled"},
{216, nullptr, "SetAllKuinaDevicesToFirmwareUpdateMode"},
{221, nullptr, "UpdateControllerColor"},
{222, nullptr, "ConnectUsbPadsAsync"},
{223, nullptr, "DisconnectUsbPadsAsync"},
{224, nullptr, "UpdateDesignInfo"},
{225, nullptr, "GetUniquePadDriverState"},
{226, nullptr, "GetSixAxisSensorDriverStates"},
{227, nullptr, "GetRxPacketHistory"},
{228, nullptr, "AcquireOperationEventHandle"},
{229, nullptr, "ReadSerialFlash"},
{230, nullptr, "WriteSerialFlash"},
{231, nullptr, "GetOperationResult"},
{232, nullptr, "EnableShipmentMode"},
{233, nullptr, "ClearPairingInfo"},
{234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
{235, nullptr, "EnableAnalogStickPower"},
{236, nullptr, "RequestKuinaUartClockCal"},
{237, nullptr, "GetKuinaUartClockCal"},
{238, nullptr, "SetKuinaUartClockTrim"},
{239, nullptr, "KuinaLoopbackTest"},
{240, nullptr, "RequestBatteryVoltage"},
{241, nullptr, "GetBatteryVoltage"},
{242, nullptr, "GetUniquePadPowerInfo"},
{243, nullptr, "RebootUniquePad"},
{244, nullptr, "RequestKuinaFirmwareVersion"},
{245, nullptr, "GetKuinaFirmwareVersion"},
{246, nullptr, "GetVidPid"},
{247, nullptr, "GetAnalogStickCalibrationValue"},
{248, nullptr, "GetUniquePadIdsFull"},
{249, nullptr, "ConnectUniquePad"},
{250, nullptr, "IsVirtual"},
{251, nullptr, "GetAnalogStickModuleParam"},
{301, nullptr, "GetAbstractedPadHandles"},
{302, nullptr, "GetAbstractedPadState"},
{303, nullptr, "GetAbstractedPadsState"},
{321, nullptr, "SetAutoPilotVirtualPadState"},
{322, nullptr, "UnsetAutoPilotVirtualPadState"},
{323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
{324, nullptr, "AttachHdlsWorkBuffer"},
{325, nullptr, "ReleaseHdlsWorkBuffer"},
{326, nullptr, "DumpHdlsNpadAssignmentState"},
{327, nullptr, "DumpHdlsStates"},
{328, nullptr, "ApplyHdlsNpadAssignmentState"},
{329, nullptr, "ApplyHdlsStateList"},
{330, nullptr, "AttachHdlsVirtualDevice"},
{331, nullptr, "DetachHdlsVirtualDevice"},
{332, nullptr, "SetHdlsState"},
{350, nullptr, "AddRegisteredDevice"},
{400, nullptr, "DisableExternalMcuOnNxDevice"},
{401, nullptr, "DisableRailDeviceFiltering"},
{402, nullptr, "EnableWiredPairing"},
{403, nullptr, "EnableShipmentModeAutoClear"},
{404, nullptr, "SetRailEnabled"},
{500, nullptr, "SetFactoryInt"},
{501, nullptr, "IsFactoryBootEnabled"},
{550, nullptr, "SetAnalogStickModelDataTemporarily"},
{551, nullptr, "GetAnalogStickModelData"},
{552, nullptr, "ResetAnalogStickModelData"},
{600, nullptr, "ConvertPadState"},
{650, nullptr, "AddButtonPlayData"},
{651, nullptr, "StartButtonPlayData"},
{652, nullptr, "StopButtonPlayData"},
{2000, nullptr, "DeactivateDigitizer"},
{2001, nullptr, "SetDigitizerAutoPilotState"},
{2002, nullptr, "UnsetDigitizerAutoPilotState"},
{2002, nullptr, "ReloadFirmwareDebugSettings"},
};
// clang-format on
RegisterHandlers(functions);
}
IHidDebugServer::~IHidDebugServer() = default;
std::shared_ptr<ResourceManager> IHidDebugServer::GetResourceManager() {
resource_manager->Initialize();
return resource_manager;
}
} // namespace Service::HID

View File

@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::HID {
class ResourceManager;
class IHidDebugServer final : public ServiceFramework<IHidDebugServer> {
public:
explicit IHidDebugServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
~IHidDebugServer() override;
private:
std::shared_ptr<ResourceManager> GetResourceManager();
std::shared_ptr<ResourceManager> resource_manager;
};
} // namespace Service::HID

View File

@@ -0,0 +1,99 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/hid/hid_firmware_settings.h"
namespace Service::HID {
HidFirmwareSettings::HidFirmwareSettings() {
LoadSettings(true);
}
void HidFirmwareSettings::Reload() {
LoadSettings(true);
}
void HidFirmwareSettings::LoadSettings(bool reload_config) {
if (is_initalized && !reload_config) {
return;
}
// TODO: Use nn::settings::fwdbg::GetSettingsItemValue to load config values
is_debug_pad_enabled = true;
is_device_managed = true;
is_touch_i2c_managed = is_device_managed;
is_future_devices_emulated = false;
is_mcu_hardware_error_emulated = false;
is_rail_enabled = true;
is_firmware_update_failure_emulated = false;
is_firmware_update_failure = {};
is_ble_disabled = false;
is_dscale_disabled = false;
is_handheld_forced = true;
features_per_id_disabled = {};
is_touch_firmware_auto_update_disabled = false;
is_initalized = true;
}
bool HidFirmwareSettings::IsDebugPadEnabled() {
LoadSettings(false);
return is_debug_pad_enabled;
}
bool HidFirmwareSettings::IsDeviceManaged() {
LoadSettings(false);
return is_device_managed;
}
bool HidFirmwareSettings::IsEmulateFutureDevice() {
LoadSettings(false);
return is_future_devices_emulated;
}
bool HidFirmwareSettings::IsTouchI2cManaged() {
LoadSettings(false);
return is_touch_i2c_managed;
}
bool HidFirmwareSettings::IsHandheldForced() {
LoadSettings(false);
return is_handheld_forced;
}
bool HidFirmwareSettings::IsRailEnabled() {
LoadSettings(false);
return is_rail_enabled;
}
bool HidFirmwareSettings::IsHardwareErrorEmulated() {
LoadSettings(false);
return is_mcu_hardware_error_emulated;
}
bool HidFirmwareSettings::IsBleDisabled() {
LoadSettings(false);
return is_ble_disabled;
}
bool HidFirmwareSettings::IsDscaleDisabled() {
LoadSettings(false);
return is_dscale_disabled;
}
bool HidFirmwareSettings::IsTouchAutoUpdateDisabled() {
LoadSettings(false);
return is_touch_firmware_auto_update_disabled;
}
HidFirmwareSettings::FirmwareSetting HidFirmwareSettings::GetFirmwareUpdateFailure() {
LoadSettings(false);
return is_firmware_update_failure;
}
HidFirmwareSettings::FeaturesPerId HidFirmwareSettings::FeaturesDisabledPerId() {
LoadSettings(false);
return features_per_id_disabled;
}
} // namespace Service::HID

View File

@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "common/common_types.h"
namespace Service::HID {
/// Loads firmware config from nn::settings::fwdbg
class HidFirmwareSettings {
public:
using FirmwareSetting = std::array<u8, 4>;
using FeaturesPerId = std::array<bool, 0xA8>;
HidFirmwareSettings();
void Reload();
void LoadSettings(bool reload_config);
bool IsDebugPadEnabled();
bool IsDeviceManaged();
bool IsEmulateFutureDevice();
bool IsTouchI2cManaged();
bool IsHandheldForced();
bool IsRailEnabled();
bool IsHardwareErrorEmulated();
bool IsBleDisabled();
bool IsDscaleDisabled();
bool IsTouchAutoUpdateDisabled();
FirmwareSetting GetFirmwareUpdateFailure();
FeaturesPerId FeaturesDisabledPerId();
private:
bool is_initalized{};
// Debug settings
bool is_debug_pad_enabled{};
bool is_device_managed{};
bool is_touch_i2c_managed{};
bool is_future_devices_emulated{};
bool is_mcu_hardware_error_emulated{};
bool is_rail_enabled{};
bool is_firmware_update_failure_emulated{};
bool is_ble_disabled{};
bool is_dscale_disabled{};
bool is_handheld_forced{};
bool is_touch_firmware_auto_update_disabled{};
FirmwareSetting is_firmware_update_failure{};
FeaturesPerId features_per_id_disabled{};
};
} // namespace Service::HID

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,149 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::HID {
class ResourceManager;
class HidFirmwareSettings;
class IHidServer final : public ServiceFramework<IHidServer> {
public:
explicit IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> resource,
std::shared_ptr<HidFirmwareSettings> settings);
~IHidServer() override;
std::shared_ptr<ResourceManager> GetResourceManager();
private:
void CreateAppletResource(HLERequestContext& ctx);
void ActivateDebugPad(HLERequestContext& ctx);
void ActivateTouchScreen(HLERequestContext& ctx);
void ActivateMouse(HLERequestContext& ctx);
void ActivateKeyboard(HLERequestContext& ctx);
void SendKeyboardLockKeyEvent(HLERequestContext& ctx);
void AcquireXpadIdEventHandle(HLERequestContext& ctx);
void ReleaseXpadIdEventHandle(HLERequestContext& ctx);
void ActivateXpad(HLERequestContext& ctx);
void GetXpadIds(HLERequestContext& ctx);
void ActivateJoyXpad(HLERequestContext& ctx);
void GetJoyXpadLifoHandle(HLERequestContext& ctx);
void GetJoyXpadIds(HLERequestContext& ctx);
void ActivateSixAxisSensor(HLERequestContext& ctx);
void DeactivateSixAxisSensor(HLERequestContext& ctx);
void GetSixAxisSensorLifoHandle(HLERequestContext& ctx);
void ActivateJoySixAxisSensor(HLERequestContext& ctx);
void DeactivateJoySixAxisSensor(HLERequestContext& ctx);
void GetJoySixAxisSensorLifoHandle(HLERequestContext& ctx);
void StartSixAxisSensor(HLERequestContext& ctx);
void StopSixAxisSensor(HLERequestContext& ctx);
void IsSixAxisSensorFusionEnabled(HLERequestContext& ctx);
void EnableSixAxisSensorFusion(HLERequestContext& ctx);
void SetSixAxisSensorFusionParameters(HLERequestContext& ctx);
void GetSixAxisSensorFusionParameters(HLERequestContext& ctx);
void ResetSixAxisSensorFusionParameters(HLERequestContext& ctx);
void SetGyroscopeZeroDriftMode(HLERequestContext& ctx);
void GetGyroscopeZeroDriftMode(HLERequestContext& ctx);
void ResetGyroscopeZeroDriftMode(HLERequestContext& ctx);
void IsSixAxisSensorAtRest(HLERequestContext& ctx);
void IsFirmwareUpdateAvailableForSixAxisSensor(HLERequestContext& ctx);
void EnableSixAxisSensorUnalteredPassthrough(HLERequestContext& ctx);
void IsSixAxisSensorUnalteredPassthroughEnabled(HLERequestContext& ctx);
void LoadSixAxisSensorCalibrationParameter(HLERequestContext& ctx);
void GetSixAxisSensorIcInformation(HLERequestContext& ctx);
void ResetIsSixAxisSensorDeviceNewlyAssigned(HLERequestContext& ctx);
void ActivateGesture(HLERequestContext& ctx);
void SetSupportedNpadStyleSet(HLERequestContext& ctx);
void GetSupportedNpadStyleSet(HLERequestContext& ctx);
void SetSupportedNpadIdType(HLERequestContext& ctx);
void ActivateNpad(HLERequestContext& ctx);
void DeactivateNpad(HLERequestContext& ctx);
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
void DisconnectNpad(HLERequestContext& ctx);
void GetPlayerLedPattern(HLERequestContext& ctx);
void ActivateNpadWithRevision(HLERequestContext& ctx);
void SetNpadJoyHoldType(HLERequestContext& ctx);
void GetNpadJoyHoldType(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeDual(HLERequestContext& ctx);
void MergeSingleJoyAsDualJoy(HLERequestContext& ctx);
void StartLrAssignmentMode(HLERequestContext& ctx);
void StopLrAssignmentMode(HLERequestContext& ctx);
void SetNpadHandheldActivationMode(HLERequestContext& ctx);
void GetNpadHandheldActivationMode(HLERequestContext& ctx);
void SwapNpadAssignment(HLERequestContext& ctx);
void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
void GetVibrationDeviceInfo(HLERequestContext& ctx);
void SendVibrationValue(HLERequestContext& ctx);
void GetActualVibrationValue(HLERequestContext& ctx);
void CreateActiveVibrationDeviceList(HLERequestContext& ctx);
void PermitVibration(HLERequestContext& ctx);
void IsVibrationPermitted(HLERequestContext& ctx);
void SendVibrationValues(HLERequestContext& ctx);
void SendVibrationGcErmCommand(HLERequestContext& ctx);
void GetActualVibrationGcErmCommand(HLERequestContext& ctx);
void BeginPermitVibrationSession(HLERequestContext& ctx);
void EndPermitVibrationSession(HLERequestContext& ctx);
void IsVibrationDeviceMounted(HLERequestContext& ctx);
void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
void StartConsoleSixAxisSensor(HLERequestContext& ctx);
void StopConsoleSixAxisSensor(HLERequestContext& ctx);
void ActivateSevenSixAxisSensor(HLERequestContext& ctx);
void StartSevenSixAxisSensor(HLERequestContext& ctx);
void StopSevenSixAxisSensor(HLERequestContext& ctx);
void InitializeSevenSixAxisSensor(HLERequestContext& ctx);
void FinalizeSevenSixAxisSensor(HLERequestContext& ctx);
void ResetSevenSixAxisSensorTimestamp(HLERequestContext& ctx);
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
void GetPalmaConnectionHandle(HLERequestContext& ctx);
void InitializePalma(HLERequestContext& ctx);
void AcquirePalmaOperationCompleteEvent(HLERequestContext& ctx);
void GetPalmaOperationInfo(HLERequestContext& ctx);
void PlayPalmaActivity(HLERequestContext& ctx);
void SetPalmaFrModeType(HLERequestContext& ctx);
void ReadPalmaStep(HLERequestContext& ctx);
void EnablePalmaStep(HLERequestContext& ctx);
void ResetPalmaStep(HLERequestContext& ctx);
void ReadPalmaApplicationSection(HLERequestContext& ctx);
void WritePalmaApplicationSection(HLERequestContext& ctx);
void ReadPalmaUniqueCode(HLERequestContext& ctx);
void SetPalmaUniqueCodeInvalid(HLERequestContext& ctx);
void WritePalmaActivityEntry(HLERequestContext& ctx);
void WritePalmaRgbLedPatternEntry(HLERequestContext& ctx);
void WritePalmaWaveEntry(HLERequestContext& ctx);
void SetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
void GetPalmaDataBaseIdentificationVersion(HLERequestContext& ctx);
void SuspendPalmaFeature(HLERequestContext& ctx);
void GetPalmaOperationResult(HLERequestContext& ctx);
void ReadPalmaPlayLog(HLERequestContext& ctx);
void ResetPalmaPlayLog(HLERequestContext& ctx);
void SetIsPalmaAllConnectable(HLERequestContext& ctx);
void SetIsPalmaPairedConnectable(HLERequestContext& ctx);
void PairPalma(HLERequestContext& ctx);
void SetPalmaBoostMode(HLERequestContext& ctx);
void CancelWritePalmaWaveEntry(HLERequestContext& ctx);
void EnablePalmaBoostMode(HLERequestContext& ctx);
void GetPalmaBluetoothAddress(HLERequestContext& ctx);
void SetDisallowedPalmaConnection(HLERequestContext& ctx);
void SetNpadCommunicationMode(HLERequestContext& ctx);
void GetNpadCommunicationMode(HLERequestContext& ctx);
void SetTouchScreenConfiguration(HLERequestContext& ctx);
void IsFirmwareUpdateNeededForNotification(HLERequestContext& ctx);
std::shared_ptr<ResourceManager> resource_manager;
std::shared_ptr<HidFirmwareSettings> firmware_settings;
};
} // namespace Service::HID

View File

@@ -0,0 +1,539 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hid/hid_core.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_system_server.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
namespace Service::HID {
IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource)
: ServiceFramework{system_, "hid:sys"}, service_context{system_, service_name},
resource_manager{resource} {
// clang-format off
static const FunctionInfo functions[] = {
{31, nullptr, "SendKeyboardLockKeyEvent"},
{101, nullptr, "AcquireHomeButtonEventHandle"},
{111, nullptr, "ActivateHomeButton"},
{121, nullptr, "AcquireSleepButtonEventHandle"},
{131, nullptr, "ActivateSleepButton"},
{141, nullptr, "AcquireCaptureButtonEventHandle"},
{151, nullptr, "ActivateCaptureButton"},
{161, nullptr, "GetPlatformConfig"},
{210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
{211, nullptr, "GetNpadsWithNfc"},
{212, nullptr, "AcquireNfcActivateEventHandle"},
{213, nullptr, "ActivateNfc"},
{214, nullptr, "GetXcdHandleForNpadWithNfc"},
{215, nullptr, "IsNfcActivated"},
{230, nullptr, "AcquireIrSensorEventHandle"},
{231, nullptr, "ActivateIrSensor"},
{232, nullptr, "GetIrSensorState"},
{233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
{301, nullptr, "ActivateNpadSystem"},
{303, &IHidSystemServer::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
{304, &IHidSystemServer::EnableAssigningSingleOnSlSrPress, "EnableAssigningSingleOnSlSrPress"},
{305, &IHidSystemServer::DisableAssigningSingleOnSlSrPress, "DisableAssigningSingleOnSlSrPress"},
{306, &IHidSystemServer::GetLastActiveNpad, "GetLastActiveNpad"},
{307, nullptr, "GetNpadSystemExtStyle"},
{308, &IHidSystemServer::ApplyNpadSystemCommonPolicyFull, "ApplyNpadSystemCommonPolicyFull"},
{309, &IHidSystemServer::GetNpadFullKeyGripColor, "GetNpadFullKeyGripColor"},
{310, &IHidSystemServer::GetMaskedSupportedNpadStyleSet, "GetMaskedSupportedNpadStyleSet"},
{311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
{312, &IHidSystemServer::SetSupportedNpadStyleSetAll, "SetSupportedNpadStyleSetAll"},
{313, nullptr, "GetNpadCaptureButtonAssignment"},
{314, nullptr, "GetAppletFooterUiType"},
{315, &IHidSystemServer::GetAppletDetailedUiType, "GetAppletDetailedUiType"},
{316, &IHidSystemServer::GetNpadInterfaceType, "GetNpadInterfaceType"},
{317, &IHidSystemServer::GetNpadLeftRightInterfaceType, "GetNpadLeftRightInterfaceType"},
{318, &IHidSystemServer::HasBattery, "HasBattery"},
{319, &IHidSystemServer::HasLeftRightBattery, "HasLeftRightBattery"},
{321, &IHidSystemServer::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
{322, &IHidSystemServer::GetIrSensorState, "GetIrSensorState"},
{323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
{324, nullptr, "GetUniquePadButtonSet"},
{325, nullptr, "GetUniquePadColor"},
{326, nullptr, "GetUniquePadAppletDetailedUiType"},
{327, nullptr, "GetAbstractedPadIdDataFromNpad"},
{328, nullptr, "AttachAbstractedPadToNpad"},
{329, nullptr, "DetachAbstractedPadAll"},
{330, nullptr, "CheckAbstractedPadConnection"},
{500, nullptr, "SetAppletResourceUserId"},
{501, nullptr, "RegisterAppletResourceUserId"},
{502, nullptr, "UnregisterAppletResourceUserId"},
{503, nullptr, "EnableAppletToGetInput"},
{504, nullptr, "SetAruidValidForVibration"},
{505, nullptr, "EnableAppletToGetSixAxisSensor"},
{506, nullptr, "EnableAppletToGetPadInput"},
{507, nullptr, "EnableAppletToGetTouchScreen"},
{510, nullptr, "SetVibrationMasterVolume"},
{511, nullptr, "GetVibrationMasterVolume"},
{512, nullptr, "BeginPermitVibrationSession"},
{513, nullptr, "EndPermitVibrationSession"},
{514, nullptr, "Unknown514"},
{520, nullptr, "EnableHandheldHids"},
{521, nullptr, "DisableHandheldHids"},
{522, nullptr, "SetJoyConRailEnabled"},
{523, nullptr, "IsJoyConRailEnabled"},
{524, nullptr, "IsHandheldHidsEnabled"},
{525, nullptr, "IsJoyConAttachedOnAllRail"},
{540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
{541, nullptr, "GetPlayReportControllerUsages"},
{542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
{543, nullptr, "GetRegisteredDevicesOld"},
{544, &IHidSystemServer::AcquireConnectionTriggerTimeoutEvent, "AcquireConnectionTriggerTimeoutEvent"},
{545, nullptr, "SendConnectionTrigger"},
{546, &IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport, "AcquireDeviceRegisteredEventForControllerSupport"},
{547, nullptr, "GetAllowedBluetoothLinksCount"},
{548, &IHidSystemServer::GetRegisteredDevices, "GetRegisteredDevices"},
{549, nullptr, "GetConnectableRegisteredDevices"},
{700, nullptr, "ActivateUniquePad"},
{702, &IHidSystemServer::AcquireUniquePadConnectionEventHandle, "AcquireUniquePadConnectionEventHandle"},
{703, &IHidSystemServer::GetUniquePadIds, "GetUniquePadIds"},
{751, &IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
{800, nullptr, "ListSixAxisSensorHandles"},
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
{803, nullptr, "StartSixAxisSensorUserCalibration"},
{804, nullptr, "CancelSixAxisSensorUserCalibration"},
{805, nullptr, "GetUniquePadBluetoothAddress"},
{806, nullptr, "DisconnectUniquePad"},
{807, nullptr, "GetUniquePadType"},
{808, nullptr, "GetUniquePadInterface"},
{809, nullptr, "GetUniquePadSerialNumber"},
{810, nullptr, "GetUniquePadControllerNumber"},
{811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
{812, nullptr, "GetConsoleUniqueSixAxisSensorHandle"},
{821, nullptr, "StartAnalogStickManualCalibration"},
{822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
{823, nullptr, "CancelAnalogStickManualCalibration"},
{824, nullptr, "ResetAnalogStickManualCalibration"},
{825, nullptr, "GetAnalogStickState"},
{826, nullptr, "GetAnalogStickManualCalibrationStage"},
{827, nullptr, "IsAnalogStickButtonPressed"},
{828, nullptr, "IsAnalogStickInReleasePosition"},
{829, nullptr, "IsAnalogStickInCircumference"},
{830, nullptr, "SetNotificationLedPattern"},
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
{832, nullptr, "PrepareHidsForNotificationWake"},
{850, &IHidSystemServer::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
{851, nullptr, "EnableUsbFullKeyController"},
{852, nullptr, "IsUsbConnected"},
{870, &IHidSystemServer::IsHandheldButtonPressedOnConsoleMode, "IsHandheldButtonPressedOnConsoleMode"},
{900, nullptr, "ActivateInputDetector"},
{901, nullptr, "NotifyInputDetector"},
{1000, &IHidSystemServer::InitializeFirmwareUpdate, "InitializeFirmwareUpdate"},
{1001, nullptr, "GetFirmwareVersion"},
{1002, nullptr, "GetAvailableFirmwareVersion"},
{1003, nullptr, "IsFirmwareUpdateAvailable"},
{1004, nullptr, "CheckFirmwareUpdateRequired"},
{1005, nullptr, "StartFirmwareUpdate"},
{1006, nullptr, "AbortFirmwareUpdate"},
{1007, nullptr, "GetFirmwareUpdateState"},
{1008, nullptr, "ActivateAudioControl"},
{1009, nullptr, "AcquireAudioControlEventHandle"},
{1010, nullptr, "GetAudioControlStates"},
{1011, nullptr, "DeactivateAudioControl"},
{1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
{1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
{1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
{1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
{1100, nullptr, "GetHidbusSystemServiceObject"},
{1120, nullptr, "SetFirmwareHotfixUpdateSkipEnabled"},
{1130, nullptr, "InitializeUsbFirmwareUpdate"},
{1131, nullptr, "FinalizeUsbFirmwareUpdate"},
{1132, nullptr, "CheckUsbFirmwareUpdateRequired"},
{1133, nullptr, "StartUsbFirmwareUpdate"},
{1134, nullptr, "GetUsbFirmwareUpdateState"},
{1135, &IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory, "InitializeUsbFirmwareUpdateWithoutMemory"},
{1150, nullptr, "SetTouchScreenMagnification"},
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
{1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
{1154, nullptr, "IsFirmwareAvailableForNotification"},
{1155, nullptr, "SetForceHandheldStyleVibration"},
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
{1157, nullptr, "CancelConnectionTrigger"},
{1200, nullptr, "IsButtonConfigSupported"},
{1201, nullptr, "IsButtonConfigEmbeddedSupported"},
{1202, nullptr, "DeleteButtonConfig"},
{1203, nullptr, "DeleteButtonConfigEmbedded"},
{1204, nullptr, "SetButtonConfigEnabled"},
{1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
{1206, nullptr, "IsButtonConfigEnabled"},
{1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
{1208, nullptr, "SetButtonConfigEmbedded"},
{1209, nullptr, "SetButtonConfigFull"},
{1210, nullptr, "SetButtonConfigLeft"},
{1211, nullptr, "SetButtonConfigRight"},
{1212, nullptr, "GetButtonConfigEmbedded"},
{1213, nullptr, "GetButtonConfigFull"},
{1214, nullptr, "GetButtonConfigLeft"},
{1215, nullptr, "GetButtonConfigRight"},
{1250, nullptr, "IsCustomButtonConfigSupported"},
{1251, nullptr, "IsDefaultButtonConfigEmbedded"},
{1252, nullptr, "IsDefaultButtonConfigFull"},
{1253, nullptr, "IsDefaultButtonConfigLeft"},
{1254, nullptr, "IsDefaultButtonConfigRight"},
{1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
{1256, nullptr, "IsButtonConfigStorageFullEmpty"},
{1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
{1258, nullptr, "IsButtonConfigStorageRightEmpty"},
{1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
{1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
{1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
{1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
{1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
{1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
{1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
{1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
{1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
{1268, nullptr, "DeleteButtonConfigStorageFull"},
{1269, nullptr, "DeleteButtonConfigStorageLeft"},
{1270, nullptr, "DeleteButtonConfigStorageRight"},
{1271, nullptr, "IsUsingCustomButtonConfig"},
{1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
{1273, nullptr, "SetAllCustomButtonConfigEnabled"},
{1274, nullptr, "SetDefaultButtonConfig"},
{1275, nullptr, "SetAllDefaultButtonConfig"},
{1276, nullptr, "SetHidButtonConfigEmbedded"},
{1277, nullptr, "SetHidButtonConfigFull"},
{1278, nullptr, "SetHidButtonConfigLeft"},
{1279, nullptr, "SetHidButtonConfigRight"},
{1280, nullptr, "GetHidButtonConfigEmbedded"},
{1281, nullptr, "GetHidButtonConfigFull"},
{1282, nullptr, "GetHidButtonConfigLeft"},
{1283, nullptr, "GetHidButtonConfigRight"},
{1284, nullptr, "GetButtonConfigStorageEmbedded"},
{1285, nullptr, "GetButtonConfigStorageFull"},
{1286, nullptr, "GetButtonConfigStorageLeft"},
{1287, nullptr, "GetButtonConfigStorageRight"},
{1288, nullptr, "SetButtonConfigStorageEmbedded"},
{1289, nullptr, "SetButtonConfigStorageFull"},
{1290, nullptr, "DeleteButtonConfigStorageRight"},
{1291, nullptr, "DeleteButtonConfigStorageRight"},
};
// clang-format on
RegisterHandlers(functions);
joy_detach_event = service_context.CreateEvent("IHidSystemServer::JoyDetachEvent");
acquire_device_registered_event =
service_context.CreateEvent("IHidSystemServer::AcquireDeviceRegisteredEvent");
acquire_connection_trigger_timeout_event =
service_context.CreateEvent("IHidSystemServer::AcquireConnectionTriggerTimeoutEvent");
unique_pad_connection_event =
service_context.CreateEvent("IHidSystemServer::AcquireUniquePadConnectionEventHandle");
}
IHidSystemServer::~IHidSystemServer() {
service_context.CloseEvent(joy_detach_event);
service_context.CloseEvent(acquire_device_registered_event);
service_context.CloseEvent(acquire_connection_trigger_timeout_event);
service_context.CloseEvent(unique_pad_connection_event);
};
void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "called");
GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::GetLastActiveNpad(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "(STUBBED) called"); // Spams a lot when controller applet is running
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(system.HIDCore().GetLastActiveController());
}
void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "called");
GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::GetNpadFullKeyGripColor(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
Core::HID::NpadColor left_color{};
Core::HID::NpadColor right_color{};
// TODO: Get colors from Npad
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.PushRaw(left_color);
rb.PushRaw(right_color);
}
void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
LOG_INFO(Service_HID, "(STUBBED) called");
Core::HID::NpadStyleSet supported_styleset =
GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(supported_styleset);
}
void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
LOG_INFO(Service_HID, "(STUBBED) called");
Core::HID::NpadStyleSet supported_styleset =
GetResourceManager()->GetNpad()->GetSupportedStyleSet().raw;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(supported_styleset);
}
void IHidSystemServer::GetAppletDetailedUiType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
const NPad::AppletDetailedUiType detailed_ui_type =
GetResourceManager()->GetNpad()->GetAppletDetailedUiType(npad_id_type);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushRaw(detailed_ui_type);
}
void IHidSystemServer::GetNpadInterfaceType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth);
}
void IHidSystemServer::GetNpadLeftRightInterfaceType(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth);
rb.PushEnum(Core::HID::NpadInterfaceType::Bluetooth);
}
void IHidSystemServer::HasBattery(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(false);
}
void IHidSystemServer::HasLeftRightBattery(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
struct LeftRightBattery {
bool left;
bool right;
};
LeftRightBattery left_right_battery{
.left = false,
.right = false,
};
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushRaw(left_right_battery);
}
void IHidSystemServer::GetUniquePadsFromNpad(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
LOG_DEBUG(Service_HID, "(STUBBED) called, npad_id_type={}",
npad_id_type); // Spams a lot when controller applet is running
const std::vector<Core::HID::UniquePadId> unique_pads{};
if (!unique_pads.empty()) {
ctx.WriteBuffer(unique_pads);
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(static_cast<u32>(unique_pads.size()));
}
void IHidSystemServer::GetIrSensorState(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx) {
LOG_INFO(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent());
}
void IHidSystemServer::AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx) {
LOG_INFO(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(acquire_device_registered_event->GetReadableEvent());
}
void IHidSystemServer::GetRegisteredDevices(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
struct RegisterData {
std::array<u8, 0x68> data;
};
static_assert(sizeof(RegisterData) == 0x68, "RegisterData is an invalid size");
std::vector<RegisterData> registered_devices{};
if (!registered_devices.empty()) {
ctx.WriteBuffer(registered_devices);
}
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u64>(registered_devices.size());
}
void IHidSystemServer::AcquireUniquePadConnectionEventHandle(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.PushCopyObjects(unique_pad_connection_event->GetReadableEvent());
rb.Push(ResultSuccess);
}
void IHidSystemServer::GetUniquePadIds(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u64>(0);
}
void IHidSystemServer::AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
LOG_INFO(Service_AM, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
}
void IHidSystemServer::IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
const bool is_enabled = false;
LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(is_enabled);
}
void IHidSystemServer::IsHandheldButtonPressedOnConsoleMode(HLERequestContext& ctx) {
const bool button_pressed = false;
LOG_DEBUG(Service_HID, "(STUBBED) called, is_enabled={}",
button_pressed); // Spams a lot when controller applet is open
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(button_pressed);
}
void IHidSystemServer::InitializeFirmwareUpdate(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
Core::HID::TouchScreenConfigurationForNx touchscreen_config{
.mode = Core::HID::TouchScreenModeForNx::Finger,
};
if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
}
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.PushRaw(touchscreen_config);
}
std::shared_ptr<ResourceManager> IHidSystemServer::GetResourceManager() {
resource_manager->Initialize();
return resource_manager;
}
} // namespace Service::HID

View File

@@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Kernel {
class KEvent;
}
namespace Service::HID {
class ResourceManager;
class IHidSystemServer final : public ServiceFramework<IHidSystemServer> {
public:
explicit IHidSystemServer(Core::System& system_, std::shared_ptr<ResourceManager> resource);
~IHidSystemServer() override;
private:
void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx);
void EnableAssigningSingleOnSlSrPress(HLERequestContext& ctx);
void DisableAssigningSingleOnSlSrPress(HLERequestContext& ctx);
void GetLastActiveNpad(HLERequestContext& ctx);
void ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx);
void GetNpadFullKeyGripColor(HLERequestContext& ctx);
void GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx);
void SetSupportedNpadStyleSetAll(HLERequestContext& ctx);
void GetAppletDetailedUiType(HLERequestContext& ctx);
void GetNpadInterfaceType(HLERequestContext& ctx);
void GetNpadLeftRightInterfaceType(HLERequestContext& ctx);
void HasBattery(HLERequestContext& ctx);
void HasLeftRightBattery(HLERequestContext& ctx);
void GetUniquePadsFromNpad(HLERequestContext& ctx);
void GetIrSensorState(HLERequestContext& ctx);
void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx);
void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx);
void GetRegisteredDevices(HLERequestContext& ctx);
void AcquireUniquePadConnectionEventHandle(HLERequestContext& ctx);
void GetUniquePadIds(HLERequestContext& ctx);
void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx);
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx);
void IsHandheldButtonPressedOnConsoleMode(HLERequestContext& ctx);
void InitializeFirmwareUpdate(HLERequestContext& ctx);
void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx);
void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx);
std::shared_ptr<ResourceManager> GetResourceManager();
Kernel::KEvent* acquire_connection_trigger_timeout_event;
Kernel::KEvent* acquire_device_registered_event;
Kernel::KEvent* joy_detach_event;
Kernel::KEvent* unique_pad_connection_event;
KernelHelpers::ServiceContext service_context;
std::shared_ptr<ResourceManager> resource_manager;
};
} // namespace Service::HID

View File

@@ -0,0 +1,146 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hid/hid_types.h"
#include "core/hle/service/hid/errors.h"
namespace Service::HID {
constexpr bool IsNpadIdValid(const Core::HID::NpadIdType npad_id) {
switch (npad_id) {
case Core::HID::NpadIdType::Player1:
case Core::HID::NpadIdType::Player2:
case Core::HID::NpadIdType::Player3:
case Core::HID::NpadIdType::Player4:
case Core::HID::NpadIdType::Player5:
case Core::HID::NpadIdType::Player6:
case Core::HID::NpadIdType::Player7:
case Core::HID::NpadIdType::Player8:
case Core::HID::NpadIdType::Other:
case Core::HID::NpadIdType::Handheld:
return true;
default:
return false;
}
}
constexpr Result IsSixaxisHandleValid(const Core::HID::SixAxisSensorHandle& handle) {
const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id));
const bool device_index = handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
if (!npad_id) {
return InvalidNpadId;
}
if (!device_index) {
return NpadDeviceIndexOutOfRange;
}
return ResultSuccess;
}
constexpr Result IsVibrationHandleValid(const Core::HID::VibrationDeviceHandle& handle) {
switch (handle.npad_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::JoyconLeft:
case Core::HID::NpadStyleIndex::JoyconRight:
case Core::HID::NpadStyleIndex::GameCube:
case Core::HID::NpadStyleIndex::N64:
case Core::HID::NpadStyleIndex::SystemExt:
case Core::HID::NpadStyleIndex::System:
// These support vibration
break;
default:
return VibrationInvalidStyleIndex;
}
if (!IsNpadIdValid(static_cast<Core::HID::NpadIdType>(handle.npad_id))) {
return VibrationInvalidNpadId;
}
if (handle.device_index >= Core::HID::DeviceIndex::MaxDeviceIndex) {
return VibrationDeviceIndexOutOfRange;
}
return ResultSuccess;
}
/// Converts a Core::HID::NpadIdType to an array index.
constexpr size_t NpadIdTypeToIndex(Core::HID::NpadIdType npad_id_type) {
switch (npad_id_type) {
case Core::HID::NpadIdType::Player1:
return 0;
case Core::HID::NpadIdType::Player2:
return 1;
case Core::HID::NpadIdType::Player3:
return 2;
case Core::HID::NpadIdType::Player4:
return 3;
case Core::HID::NpadIdType::Player5:
return 4;
case Core::HID::NpadIdType::Player6:
return 5;
case Core::HID::NpadIdType::Player7:
return 6;
case Core::HID::NpadIdType::Player8:
return 7;
case Core::HID::NpadIdType::Handheld:
return 8;
case Core::HID::NpadIdType::Other:
return 9;
default:
return 8;
}
}
/// Converts an array index to a Core::HID::NpadIdType
constexpr Core::HID::NpadIdType IndexToNpadIdType(size_t index) {
switch (index) {
case 0:
return Core::HID::NpadIdType::Player1;
case 1:
return Core::HID::NpadIdType::Player2;
case 2:
return Core::HID::NpadIdType::Player3;
case 3:
return Core::HID::NpadIdType::Player4;
case 4:
return Core::HID::NpadIdType::Player5;
case 5:
return Core::HID::NpadIdType::Player6;
case 6:
return Core::HID::NpadIdType::Player7;
case 7:
return Core::HID::NpadIdType::Player8;
case 8:
return Core::HID::NpadIdType::Handheld;
case 9:
return Core::HID::NpadIdType::Other;
default:
return Core::HID::NpadIdType::Invalid;
}
}
constexpr Core::HID::NpadStyleSet GetStylesetByIndex(std::size_t index) {
switch (index) {
case 0:
return Core::HID::NpadStyleSet::Fullkey;
case 1:
return Core::HID::NpadStyleSet::Handheld;
case 2:
return Core::HID::NpadStyleSet::JoyDual;
case 3:
return Core::HID::NpadStyleSet::JoyLeft;
case 4:
return Core::HID::NpadStyleSet::JoyRight;
case 5:
return Core::HID::NpadStyleSet::Palma;
default:
return Core::HID::NpadStyleSet::None;
}
}
} // namespace Service::HID

View File

@@ -12,6 +12,7 @@
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/hid/irs.h"
#include "core/hle/service/hid/irsensor/clustering_processor.h"
#include "core/hle/service/hid/irsensor/image_transfer_processor.h"
@@ -320,7 +321,7 @@ void IRS::GetNpadIrCameraHandle(HLERequestContext& ctx) {
}
Core::IrSensor::IrCameraHandle camera_handle{
.npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),
.npad_id = static_cast<u8>(HID::NpadIdTypeToIndex(npad_id)),
.npad_type = Core::HID::NpadStyleIndex::None,
};
@@ -545,7 +546,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(HLERequestContext& ctx) {
Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const {
if (camera_handle.npad_id >
static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
static_cast<u8>(HID::NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
return InvalidIrCameraHandle;
}
if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) {

View File

@@ -3,15 +3,12 @@
#pragma once
#include "core/core.h"
#include "core/hid/hid_types.h"
#include "core/hid/irs_types.h"
#include "core/hle/service/hid/irsensor/processor_base.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Core::HID {
class EmulatedController;
} // namespace Core::HID

View File

@@ -0,0 +1,241 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common/logging/log.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hid/hid_core.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/hid/controllers/console_six_axis.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
#include "core/hle/service/hid/controllers/gesture.h"
#include "core/hle/service/hid/controllers/keyboard.h"
#include "core/hle/service/hid/controllers/mouse.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/palma.h"
#include "core/hle/service/hid/controllers/seven_six_axis.h"
#include "core/hle/service/hid/controllers/six_axis.h"
#include "core/hle/service/hid/controllers/stubbed.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
#include "core/hle/service/hid/controllers/xpad.h"
namespace Service::HID {
// Updating period for each HID device.
// Period time is obtained by measuring the number of samples in a second on HW using a homebrew
// Correct npad_update_ns is 4ms this is overclocked to lower input lag
constexpr auto npad_update_ns = std::chrono::nanoseconds{1 * 1000 * 1000}; // (1ms, 1000Hz)
constexpr auto default_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 1000Hz)
constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz)
ResourceManager::ResourceManager(Core::System& system_)
: system{system_}, service_context{system_, "hid"} {}
ResourceManager::~ResourceManager() = default;
void ResourceManager::Initialize() {
if (is_initialized) {
return;
}
u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
debug_pad = std::make_shared<DebugPad>(system.HIDCore(), shared_memory);
mouse = std::make_shared<Mouse>(system.HIDCore(), shared_memory);
debug_mouse = std::make_shared<DebugMouse>(system.HIDCore(), shared_memory);
keyboard = std::make_shared<Keyboard>(system.HIDCore(), shared_memory);
unique_pad = std::make_shared<UniquePad>(system.HIDCore(), shared_memory);
npad = std::make_shared<NPad>(system.HIDCore(), shared_memory, service_context);
gesture = std::make_shared<Gesture>(system.HIDCore(), shared_memory);
touch_screen = std::make_shared<TouchScreen>(system.HIDCore(), shared_memory);
xpad = std::make_shared<XPad>(system.HIDCore(), shared_memory);
palma = std::make_shared<Palma>(system.HIDCore(), shared_memory, service_context);
home_button = std::make_shared<HomeButton>(system.HIDCore(), shared_memory);
sleep_button = std::make_shared<SleepButton>(system.HIDCore(), shared_memory);
capture_button = std::make_shared<CaptureButton>(system.HIDCore(), shared_memory);
six_axis = std::make_shared<SixAxis>(system.HIDCore(), npad);
console_six_axis = std::make_shared<ConsoleSixAxis>(system.HIDCore(), shared_memory);
seven_six_axis = std::make_shared<SevenSixAxis>(system);
home_button->SetCommonHeaderOffset(0x4C00);
sleep_button->SetCommonHeaderOffset(0x4E00);
capture_button->SetCommonHeaderOffset(0x5000);
unique_pad->SetCommonHeaderOffset(0x5A00);
debug_mouse->SetCommonHeaderOffset(0x3DC00);
// Homebrew doesn't try to activate some controllers, so we activate them by default
npad->Activate();
six_axis->Activate();
touch_screen->Activate();
system.HIDCore().ReloadInputDevices();
is_initialized = true;
}
std::shared_ptr<CaptureButton> ResourceManager::GetCaptureButton() const {
return capture_button;
}
std::shared_ptr<ConsoleSixAxis> ResourceManager::GetConsoleSixAxis() const {
return console_six_axis;
}
std::shared_ptr<DebugMouse> ResourceManager::GetDebugMouse() const {
return debug_mouse;
}
std::shared_ptr<DebugPad> ResourceManager::GetDebugPad() const {
return debug_pad;
}
std::shared_ptr<Gesture> ResourceManager::GetGesture() const {
return gesture;
}
std::shared_ptr<HomeButton> ResourceManager::GetHomeButton() const {
return home_button;
}
std::shared_ptr<Keyboard> ResourceManager::GetKeyboard() const {
return keyboard;
}
std::shared_ptr<Mouse> ResourceManager::GetMouse() const {
return mouse;
}
std::shared_ptr<NPad> ResourceManager::GetNpad() const {
return npad;
}
std::shared_ptr<Palma> ResourceManager::GetPalma() const {
return palma;
}
std::shared_ptr<SevenSixAxis> ResourceManager::GetSevenSixAxis() const {
return seven_six_axis;
}
std::shared_ptr<SixAxis> ResourceManager::GetSixAxis() const {
return six_axis;
}
std::shared_ptr<SleepButton> ResourceManager::GetSleepButton() const {
return sleep_button;
}
std::shared_ptr<TouchScreen> ResourceManager::GetTouchScreen() const {
return touch_screen;
}
std::shared_ptr<UniquePad> ResourceManager::GetUniquePad() const {
return unique_pad;
}
void ResourceManager::UpdateControllers(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
debug_pad->OnUpdate(core_timing);
unique_pad->OnUpdate(core_timing);
gesture->OnUpdate(core_timing);
touch_screen->OnUpdate(core_timing);
palma->OnUpdate(core_timing);
home_button->OnUpdate(core_timing);
sleep_button->OnUpdate(core_timing);
capture_button->OnUpdate(core_timing);
xpad->OnUpdate(core_timing);
}
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
npad->OnUpdate(core_timing);
}
void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
mouse->OnUpdate(core_timing);
debug_mouse->OnUpdate(core_timing);
keyboard->OnUpdate(core_timing);
}
void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
auto& core_timing = system.CoreTiming();
six_axis->OnUpdate(core_timing);
seven_six_axis->OnUpdate(core_timing);
console_six_axis->OnUpdate(core_timing);
}
IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource)
: ServiceFramework{system_, "IAppletResource"} {
static const FunctionInfo functions[] = {
{0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
};
RegisterHandlers(functions);
resource->Initialize();
// Register update callbacks
npad_update_event = Core::Timing::CreateEvent(
"HID::UpdatePadCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateNpad(user_data, ns_late);
return std::nullopt;
});
default_update_event = Core::Timing::CreateEvent(
"HID::UpdateDefaultCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateControllers(user_data, ns_late);
return std::nullopt;
});
mouse_keyboard_update_event = Core::Timing::CreateEvent(
"HID::UpdateMouseKeyboardCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateMouseKeyboard(user_data, ns_late);
return std::nullopt;
});
motion_update_event = Core::Timing::CreateEvent(
"HID::UpdateMotionCallback",
[this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
-> std::optional<std::chrono::nanoseconds> {
const auto guard = LockService();
resource->UpdateMotion(user_data, ns_late);
return std::nullopt;
});
system.CoreTiming().ScheduleLoopingEvent(npad_update_ns, npad_update_ns, npad_update_event);
system.CoreTiming().ScheduleLoopingEvent(default_update_ns, default_update_ns,
default_update_event);
system.CoreTiming().ScheduleLoopingEvent(mouse_keyboard_update_ns, mouse_keyboard_update_ns,
mouse_keyboard_update_event);
system.CoreTiming().ScheduleLoopingEvent(motion_update_ns, motion_update_ns,
motion_update_event);
}
IAppletResource::~IAppletResource() {
system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
system.CoreTiming().UnscheduleEvent(default_update_event, 0);
system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
}
void IAppletResource::GetSharedMemoryHandle(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(&system.Kernel().GetHidSharedMem());
}
} // namespace Service::HID

View File

@@ -0,0 +1,111 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Core::Timing {
struct EventType;
}
namespace Service::HID {
class Controller_Stubbed;
class ConsoleSixAxis;
class DebugPad;
class Gesture;
class Keyboard;
class Mouse;
class NPad;
class Palma;
class SevenSixAxis;
class SixAxis;
class TouchScreen;
class XPad;
using CaptureButton = Controller_Stubbed;
using DebugMouse = Controller_Stubbed;
using HomeButton = Controller_Stubbed;
using SleepButton = Controller_Stubbed;
using UniquePad = Controller_Stubbed;
class ResourceManager {
public:
explicit ResourceManager(Core::System& system_);
~ResourceManager();
void Initialize();
std::shared_ptr<CaptureButton> GetCaptureButton() const;
std::shared_ptr<ConsoleSixAxis> GetConsoleSixAxis() const;
std::shared_ptr<DebugMouse> GetDebugMouse() const;
std::shared_ptr<DebugPad> GetDebugPad() const;
std::shared_ptr<Gesture> GetGesture() const;
std::shared_ptr<HomeButton> GetHomeButton() const;
std::shared_ptr<Keyboard> GetKeyboard() const;
std::shared_ptr<Mouse> GetMouse() const;
std::shared_ptr<NPad> GetNpad() const;
std::shared_ptr<Palma> GetPalma() const;
std::shared_ptr<SevenSixAxis> GetSevenSixAxis() const;
std::shared_ptr<SixAxis> GetSixAxis() const;
std::shared_ptr<SleepButton> GetSleepButton() const;
std::shared_ptr<TouchScreen> GetTouchScreen() const;
std::shared_ptr<UniquePad> GetUniquePad() const;
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
private:
bool is_initialized{false};
std::shared_ptr<CaptureButton> capture_button = nullptr;
std::shared_ptr<ConsoleSixAxis> console_six_axis = nullptr;
std::shared_ptr<DebugMouse> debug_mouse = nullptr;
std::shared_ptr<DebugPad> debug_pad = nullptr;
std::shared_ptr<Gesture> gesture = nullptr;
std::shared_ptr<HomeButton> home_button = nullptr;
std::shared_ptr<Keyboard> keyboard = nullptr;
std::shared_ptr<Mouse> mouse = nullptr;
std::shared_ptr<NPad> npad = nullptr;
std::shared_ptr<Palma> palma = nullptr;
std::shared_ptr<SevenSixAxis> seven_six_axis = nullptr;
std::shared_ptr<SixAxis> six_axis = nullptr;
std::shared_ptr<SleepButton> sleep_button = nullptr;
std::shared_ptr<TouchScreen> touch_screen = nullptr;
std::shared_ptr<UniquePad> unique_pad = nullptr;
std::shared_ptr<XPad> xpad = nullptr;
// TODO: Create these resources
// std::shared_ptr<AudioControl> audio_control = nullptr;
// std::shared_ptr<ButtonConfig> button_config = nullptr;
// std::shared_ptr<Config> config = nullptr;
// std::shared_ptr<Connection> connection = nullptr;
// std::shared_ptr<CustomConfig> custom_config = nullptr;
// std::shared_ptr<Digitizer> digitizer = nullptr;
// std::shared_ptr<Hdls> hdls = nullptr;
// std::shared_ptr<PlayReport> play_report = nullptr;
// std::shared_ptr<Rail> rail = nullptr;
Core::System& system;
KernelHelpers::ServiceContext service_context;
};
class IAppletResource final : public ServiceFramework<IAppletResource> {
public:
explicit IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource);
~IAppletResource() override;
private:
void GetSharedMemoryHandle(HLERequestContext& ctx);
std::shared_ptr<Core::Timing::EventType> npad_update_event;
std::shared_ptr<Core::Timing::EventType> default_update_event;
std::shared_ptr<Core::Timing::EventType> mouse_keyboard_update_event;
std::shared_ptr<Core::Timing::EventType> motion_update_event;
};
} // namespace Service::HID

View File

@@ -115,12 +115,20 @@ public:
{400, nullptr, "InitializeSystem"},
{401, nullptr, "FinalizeSystem"},
{402, nullptr, "SetOperationMode"},
{403, nullptr, "InitializeSystem2"},
{403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void InitializeSystem2(HLERequestContext& ctx) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
class IUserLocalCommunicationService final

View File

@@ -7,6 +7,7 @@
#include "core/core.h"
#include "core/hid/hid_types.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/nfc/common/device.h"
#include "core/hle/service/nfc/common/device_manager.h"
@@ -24,7 +25,7 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex
for (u32 device_index = 0; device_index < devices.size(); device_index++) {
devices[device_index] =
std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
std::make_shared<NfcDevice>(HID::IndexToNpadIdType(device_index), system,
service_context, availability_change_event);
}

View File

@@ -15,7 +15,7 @@
namespace Service::android {
struct GraphicBuffer;
class GraphicBuffer;
class BufferItem final {
public:

View File

@@ -5,7 +5,6 @@
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/buffer_item.h"
#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
@@ -14,9 +13,8 @@
namespace Service::android {
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
Service::Nvidia::NvCore::NvMap& nvmap_)
: core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
: core{std::move(core_)}, slots{core->slots} {}
BufferQueueConsumer::~BufferQueueConsumer() = default;
@@ -136,8 +134,6 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
slots[slot].buffer_state = BufferState::Free;
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
listener = core->connected_producer_listener;
LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
@@ -175,6 +171,25 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_
return Status::NoError;
}
Status BufferQueueConsumer::Disconnect() {
LOG_DEBUG(Service_Nvnflinger, "called");
std::scoped_lock lock{core->mutex};
if (core->consumer_listener == nullptr) {
LOG_ERROR(Service_Nvnflinger, "no consumer is connected");
return Status::BadValue;
}
core->is_abandoned = true;
core->consumer_listener = nullptr;
core->queue.clear();
core->FreeAllBuffersLocked();
core->SignalDequeueCondition();
return Status::NoError;
}
Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
if (out_slot_mask == nullptr) {
LOG_ERROR(Service_Nvnflinger, "out_slot_mask may not be nullptr");

View File

@@ -13,10 +13,6 @@
#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
#include "core/hle/service/nvnflinger/status.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android {
class BufferItem;
@@ -25,19 +21,18 @@ class IConsumerListener;
class BufferQueueConsumer final {
public:
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_,
Service::Nvidia::NvCore::NvMap& nvmap_);
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
~BufferQueueConsumer();
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
Status Disconnect();
Status GetReleasedBuffers(u64* out_slot_mask);
private:
std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots;
Service::Nvidia::NvCore::NvMap& nvmap;
};
} // namespace Service::android

View File

@@ -14,24 +14,12 @@ BufferQueueCore::BufferQueueCore() = default;
BufferQueueCore::~BufferQueueCore() = default;
void BufferQueueCore::NotifyShutdown() {
std::scoped_lock lock{mutex};
is_shutting_down = true;
SignalDequeueCondition();
}
void BufferQueueCore::SignalDequeueCondition() {
dequeue_possible.store(true);
dequeue_condition.notify_all();
}
bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) {
if (is_shutting_down) {
return false;
}
dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); });
dequeue_possible.store(false);

View File

@@ -34,8 +34,6 @@ public:
BufferQueueCore();
~BufferQueueCore();
void NotifyShutdown();
private:
void SignalDequeueCondition();
bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);
@@ -74,7 +72,6 @@ private:
u32 transform_hint{};
bool is_allocating{};
mutable std::condition_variable_any is_allocating_condition;
bool is_shutting_down{};
};
} // namespace Service::android

View File

@@ -13,7 +13,6 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/hle_ipc.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
#include "core/hle/service/nvnflinger/consumer_listener.h"
@@ -533,8 +532,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
item.is_droppable = core->dequeue_buffer_cannot_block || async;
item.swap_interval = swap_interval;
nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true);
sticky_transform = sticky_transform_;
if (core->queue.empty()) {
@@ -744,19 +741,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
return Status::NoError;
}
// HACK: We are not Android. Remove handle for items in queue, and clear queue.
// Allows synchronous destruction of nvmap handles.
for (auto& item : core->queue) {
nvmap.FreeHandle(item.graphic_buffer->BufferId(), true);
}
core->queue.clear();
switch (api) {
case NativeWindowApi::Egl:
case NativeWindowApi::Cpu:
case NativeWindowApi::Media:
case NativeWindowApi::Camera:
if (core->connected_api == api) {
core->queue.clear();
core->FreeAllBuffersLocked();
core->connected_producer_listener = nullptr;
core->connected_api = NativeWindowApi::NoConnectedApi;
@@ -785,7 +776,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
}
Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
const std::shared_ptr<GraphicBuffer>& buffer) {
const std::shared_ptr<NvGraphicBuffer>& buffer) {
LOG_DEBUG(Service_Nvnflinger, "slot {}", slot);
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
@@ -796,7 +787,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
slots[slot] = {};
slots[slot].fence = Fence::NoFence();
slots[slot].graphic_buffer = buffer;
slots[slot].graphic_buffer = std::make_shared<GraphicBuffer>(nvmap, buffer);
slots[slot].frame_number = 0;
// Most games preallocate a buffer and pass a valid buffer here. However, it is possible for
@@ -839,7 +830,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
}
case TransactionId::SetPreallocatedBuffer: {
const auto slot = parcel_in.Read<s32>();
const auto buffer = parcel_in.ReadObject<GraphicBuffer>();
const auto buffer = parcel_in.ReadObject<NvGraphicBuffer>();
status = SetPreallocatedBuffer(slot, buffer);
break;
@@ -867,7 +858,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
status = RequestBuffer(slot, &buf);
parcel_out.WriteFlattenedObject(buf);
parcel_out.WriteFlattenedObject<NvGraphicBuffer>(buf.get());
break;
}
case TransactionId::QueueBuffer: {

View File

@@ -38,6 +38,7 @@ namespace Service::android {
class BufferQueueCore;
class IProducerListener;
struct NvGraphicBuffer;
class BufferQueueProducer final : public IBinder {
public:
@@ -65,7 +66,7 @@ public:
bool producer_controlled_by_app, QueueBufferOutput* output);
Status Disconnect(NativeWindowApi api);
Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer);
Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<NvGraphicBuffer>& buffer);
private:
BufferQueueProducer(const BufferQueueProducer&) = delete;

View File

@@ -13,7 +13,7 @@
namespace Service::android {
struct GraphicBuffer;
class GraphicBuffer;
enum class BufferState : u32 {
Free = 0,

View File

@@ -27,6 +27,26 @@ void ConsumerBase::Connect(bool controlled_by_app) {
consumer->Connect(shared_from_this(), controlled_by_app);
}
void ConsumerBase::Abandon() {
LOG_DEBUG(Service_Nvnflinger, "called");
std::scoped_lock lock{mutex};
if (!is_abandoned) {
this->AbandonLocked();
is_abandoned = true;
}
}
void ConsumerBase::AbandonLocked() {
for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
this->FreeBufferLocked(i);
}
// disconnect from the BufferQueue
consumer->Disconnect();
consumer = nullptr;
}
void ConsumerBase::FreeBufferLocked(s32 slot_index) {
LOG_DEBUG(Service_Nvnflinger, "slot_index={}", slot_index);

View File

@@ -24,6 +24,7 @@ class BufferQueueConsumer;
class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> {
public:
void Connect(bool controlled_by_app);
void Abandon();
protected:
explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
@@ -34,6 +35,7 @@ protected:
void OnBuffersReleased() override;
void OnSidebandStreamChanged() override;
void AbandonLocked();
void FreeBufferLocked(s32 slot_index);
Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when);
Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer);

View File

@@ -166,7 +166,7 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
}();
void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
auto buffer = std::make_shared<android::GraphicBuffer>();
auto buffer = std::make_shared<android::NvGraphicBuffer>();
buffer->width = SharedBufferWidth;
buffer->height = SharedBufferHeight;
buffer->stride = SharedBufferBlockLinearStride;

View File

@@ -47,7 +47,10 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) {
vsync_signal.Wait();
const auto lock_guard = Lock();
Compose();
if (!is_abandoned) {
Compose();
}
}
}
@@ -98,7 +101,6 @@ Nvnflinger::~Nvnflinger() {
}
ShutdownLayers();
vsync_thread = {};
if (nvdrv) {
nvdrv->Close(disp_fd);
@@ -106,12 +108,20 @@ Nvnflinger::~Nvnflinger() {
}
void Nvnflinger::ShutdownLayers() {
const auto lock_guard = Lock();
for (auto& display : displays) {
for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
display.GetLayer(layer).Core().NotifyShutdown();
// Abandon consumers.
{
const auto lock_guard = Lock();
for (auto& display : displays) {
for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
display.GetLayer(layer).GetConsumer().Abandon();
}
}
is_abandoned = true;
}
// Join the vsync thread, if it exists.
vsync_thread = {};
}
void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {

View File

@@ -140,6 +140,8 @@ private:
s32 swap_interval = 1;
bool is_abandoned = false;
/// Event that handles screen composition.
std::shared_ptr<Core::Timing::EventType> multi_composition_event;
std::shared_ptr<Core::Timing::EventType> single_composition_event;

View File

@@ -19,7 +19,7 @@ enum class Status : s32 {
Busy = -16,
NoInit = -19,
BadValue = -22,
InvalidOperation = -37,
InvalidOperation = -38,
BufferNeedsReallocation = 1,
ReleaseAllBuffers = 2,
};

View File

@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
namespace Service::android {
static NvGraphicBuffer GetBuffer(std::shared_ptr<NvGraphicBuffer>& buffer) {
if (buffer) {
return *buffer;
} else {
return {};
}
}
GraphicBuffer::GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
: NvGraphicBuffer(width_, height_, format_, usage_), m_nvmap(nullptr) {}
GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
std::shared_ptr<NvGraphicBuffer> buffer)
: NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
if (this->BufferId() > 0) {
m_nvmap->DuplicateHandle(this->BufferId(), true);
}
}
GraphicBuffer::~GraphicBuffer() {
if (m_nvmap != nullptr && this->BufferId() > 0) {
m_nvmap->FreeHandle(this->BufferId(), true);
}
}
} // namespace Service::android

View File

@@ -6,16 +6,22 @@
#pragma once
#include <memory>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/hle/service/nvnflinger/pixel_format.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android {
struct GraphicBuffer final {
constexpr GraphicBuffer() = default;
struct NvGraphicBuffer {
constexpr NvGraphicBuffer() = default;
constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
constexpr NvGraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
: width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_},
usage{static_cast<s32>(usage_)} {}
@@ -93,6 +99,17 @@ struct GraphicBuffer final {
u32 offset{};
INSERT_PADDING_WORDS(60);
};
static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size");
static_assert(sizeof(NvGraphicBuffer) == 0x16C, "NvGraphicBuffer has wrong size");
class GraphicBuffer final : public NvGraphicBuffer {
public:
explicit GraphicBuffer(u32 width, u32 height, PixelFormat format, u32 usage);
explicit GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
std::shared_ptr<NvGraphicBuffer> buffer);
~GraphicBuffer();
private:
Service::Nvidia::NvCore::NvMap* m_nvmap{};
};
} // namespace Service::android

View File

@@ -431,8 +431,7 @@ void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) {
u8 battery_percentage_flag{1};
LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}",
battery_percentage_flag);
LOG_DEBUG(Service_SET, "(STUBBED) called, battery_percentage_flag={}", battery_percentage_flag);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
@@ -492,6 +491,29 @@ void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) {
rb.PushEnum(ChineseTraditionalInputMethod::Unknown0);
}
void SET_SYS::GetHomeMenuScheme(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "(STUBBED) called");
const HomeMenuScheme default_color = {
.main = 0xFF323232,
.back = 0xFF323232,
.sub = 0xFFFFFFFF,
.bezel = 0xFFFFFFFF,
.extra = 0xFF000000,
};
IPC::ResponseBuilder rb{ctx, 7};
rb.Push(ResultSuccess);
rb.PushRaw(default_color);
}
void SET_SYS::GetHomeMenuSchemeModel(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called");
@@ -674,7 +696,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{171, nullptr, "SetChineseTraditionalInputMethod"},
{172, nullptr, "GetPtmCycleCountReliability"},
{173, nullptr, "SetPtmCycleCountReliability"},
{174, nullptr, "GetHomeMenuScheme"},
{174, &SET_SYS::GetHomeMenuScheme, "GetHomeMenuScheme"},
{175, nullptr, "GetThemeSettings"},
{176, nullptr, "SetThemeSettings"},
{177, nullptr, "GetThemeKey"},
@@ -685,7 +707,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
{182, nullptr, "SetT"},
{183, nullptr, "GetPlatformRegion"},
{184, nullptr, "SetPlatformRegion"},
{185, nullptr, "GetHomeMenuSchemeModel"},
{185, &SET_SYS::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"},
{186, nullptr, "GetMemoryUsageRateFlag"},
{187, nullptr, "GetTouchScreenMode"},
{188, nullptr, "SetTouchScreenMode"},

View File

@@ -269,6 +269,16 @@ private:
};
static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size");
/// This is nn::settings::system::HomeMenuScheme
struct HomeMenuScheme {
u32 main;
u32 back;
u32 sub;
u32 bezel;
u32 extra;
};
static_assert(sizeof(HomeMenuScheme) == 0x14, "HomeMenuScheme is incorrect size");
void SetLanguageCode(HLERequestContext& ctx);
void GetFirmwareVersion(HLERequestContext& ctx);
void GetFirmwareVersion2(HLERequestContext& ctx);
@@ -305,6 +315,8 @@ private:
void GetKeyboardLayout(HLERequestContext& ctx);
void GetChineseTraditionalInputMethod(HLERequestContext& ctx);
void GetFieldTestingFlag(HLERequestContext& ctx);
void GetHomeMenuScheme(HLERequestContext& ctx);
void GetHomeMenuSchemeModel(HLERequestContext& ctx);
AccountSettings account_settings{
.flags = {},

View File

@@ -35,7 +35,7 @@ static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_cont
return {
buffer_queue_core,
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)};
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
}
Display::Display(u64 id, std::string name_,

View File

@@ -1,8 +1,10 @@
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <cstring>
#include <mutex>
#include <span>
#include "common/assert.h"
@@ -10,6 +12,7 @@
#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/scope_exit.h"
#include "common/settings.h"
#include "common/swap.h"
#include "core/core.h"
@@ -318,7 +321,7 @@ struct Memory::Impl {
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) {
if constexpr (!UNSAFE) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount);
HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
}
std::memcpy(host_ptr, src_buffer, copy_amount);
},
@@ -351,7 +354,7 @@ struct Memory::Impl {
},
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount);
HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
std::memset(host_ptr, 0, copy_amount);
},
[](const std::size_t copy_amount) {});
@@ -420,7 +423,7 @@ struct Memory::Impl {
const std::size_t block_size) {
// dc cvac: Store to point of coherency
// CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
};
return PerformCacheOperation(dest_addr, size, on_rasterizer);
}
@@ -430,7 +433,7 @@ struct Memory::Impl {
const std::size_t block_size) {
// dc civac: Store to point of coherency, and invalidate from cache
// CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
};
return PerformCacheOperation(dest_addr, size, on_rasterizer);
}
@@ -767,7 +770,18 @@ struct Memory::Impl {
}
void HandleRasterizerWrite(VAddr address, size_t size) {
const size_t core = system.GetCurrentHostThreadID();
constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
const size_t core = std::min(system.GetCurrentHostThreadID(),
sys_core); // any other calls threads go to syscore.
// Guard on sys_core;
if (core == sys_core) [[unlikely]] {
sys_core_guard.lock();
}
SCOPE_EXIT({
if (core == sys_core) [[unlikely]] {
sys_core_guard.unlock();
}
});
auto& current_area = rasterizer_write_areas[core];
VAddr subaddress = address >> YUZU_PAGEBITS;
bool do_collection = current_area.last_address == subaddress;
@@ -799,6 +813,7 @@ struct Memory::Impl {
rasterizer_read_areas{};
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
std::mutex sys_core_guard;
};
Memory::Memory(Core::System& system_) : system{system_} {

View File

@@ -10,7 +10,8 @@
#include "core/hle/kernel/k_page_table.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/hid_server.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/sm/sm.h"
#include "core/memory.h"
#include "core/memory/cheat_engine.h"
@@ -54,23 +55,20 @@ void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size)
}
u64 StandardVmCallbacks::HidKeysDown() {
const auto hid = system.ServiceManager().GetService<Service::HID::Hid>("hid");
const auto hid = system.ServiceManager().GetService<Service::HID::IHidServer>("hid");
if (hid == nullptr) {
LOG_WARNING(CheatEngine, "Attempted to read input state, but hid is not initialized!");
return 0;
}
const auto applet_resource = hid->GetAppletResource();
const auto applet_resource = hid->GetResourceManager();
if (applet_resource == nullptr) {
LOG_WARNING(CheatEngine,
"Attempted to read input state, but applet resource is not initialized!");
return 0;
}
const auto press_state =
applet_resource
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)
.GetAndResetPressState();
const auto press_state = applet_resource->GetNpad()->GetAndResetPressState();
return static_cast<u64>(press_state & HID::NpadButton::All);
}

View File

@@ -415,7 +415,7 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
// This list is missing ZL/ZR since those are not considered buttons.
// We will add those afterwards
// This list also excludes any button that can't be really mapped
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 12>
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 14>
switch_to_gcadapter_button = {
std::pair{Settings::NativeButton::A, PadButton::ButtonA},
{Settings::NativeButton::B, PadButton::ButtonB},
@@ -426,8 +426,10 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
{Settings::NativeButton::DUp, PadButton::ButtonUp},
{Settings::NativeButton::DRight, PadButton::ButtonRight},
{Settings::NativeButton::DDown, PadButton::ButtonDown},
{Settings::NativeButton::SL, PadButton::TriggerL},
{Settings::NativeButton::SR, PadButton::TriggerR},
{Settings::NativeButton::SLLeft, PadButton::TriggerL},
{Settings::NativeButton::SRLeft, PadButton::TriggerR},
{Settings::NativeButton::SLRight, PadButton::TriggerL},
{Settings::NativeButton::SRRight, PadButton::TriggerR},
{Settings::NativeButton::R, PadButton::TriggerZ},
};
if (!params.Has("port")) {

View File

@@ -680,8 +680,8 @@ ButtonMapping Joycons::GetButtonMappingForDevice(const Common::ParamPackage& par
Common::ParamPackage sr_button_params = button_params;
sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSL));
sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSR));
mapping.insert_or_assign(Settings::NativeButton::SL, std::move(sl_button_params));
mapping.insert_or_assign(Settings::NativeButton::SR, std::move(sr_button_params));
mapping.insert_or_assign(Settings::NativeButton::SLLeft, std::move(sl_button_params));
mapping.insert_or_assign(Settings::NativeButton::SRLeft, std::move(sr_button_params));
}
// Map SL and SR buttons for right joycons
@@ -693,8 +693,8 @@ ButtonMapping Joycons::GetButtonMappingForDevice(const Common::ParamPackage& par
Common::ParamPackage sr_button_params = button_params;
sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSL));
sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSR));
mapping.insert_or_assign(Settings::NativeButton::SL, std::move(sl_button_params));
mapping.insert_or_assign(Settings::NativeButton::SR, std::move(sr_button_params));
mapping.insert_or_assign(Settings::NativeButton::SLRight, std::move(sl_button_params));
mapping.insert_or_assign(Settings::NativeButton::SRRight, std::move(sr_button_params));
}
return mapping;

View File

@@ -828,16 +828,18 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p
ButtonBindings SDLDriver::GetDefaultButtonBinding(
const std::shared_ptr<SDLJoystick>& joystick) const {
// Default SL/SR mapping for other controllers
auto sl_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
auto sr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
auto sll_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
auto srl_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
auto slr_button = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
auto srr_button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
if (joystick->IsJoyconLeft()) {
sl_button = SDL_CONTROLLER_BUTTON_PADDLE2;
sr_button = SDL_CONTROLLER_BUTTON_PADDLE4;
sll_button = SDL_CONTROLLER_BUTTON_PADDLE2;
srl_button = SDL_CONTROLLER_BUTTON_PADDLE4;
}
if (joystick->IsJoyconRight()) {
sl_button = SDL_CONTROLLER_BUTTON_PADDLE3;
sr_button = SDL_CONTROLLER_BUTTON_PADDLE1;
slr_button = SDL_CONTROLLER_BUTTON_PADDLE3;
srr_button = SDL_CONTROLLER_BUTTON_PADDLE1;
}
return {
@@ -855,8 +857,10 @@ ButtonBindings SDLDriver::GetDefaultButtonBinding(
{Settings::NativeButton::DUp, SDL_CONTROLLER_BUTTON_DPAD_UP},
{Settings::NativeButton::DRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
{Settings::NativeButton::DDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
{Settings::NativeButton::SL, sl_button},
{Settings::NativeButton::SR, sr_button},
{Settings::NativeButton::SLLeft, sll_button},
{Settings::NativeButton::SRLeft, srl_button},
{Settings::NativeButton::SLRight, slr_button},
{Settings::NativeButton::SRRight, srr_button},
{Settings::NativeButton::Home, SDL_CONTROLLER_BUTTON_GUIDE},
{Settings::NativeButton::Screenshot, SDL_CONTROLLER_BUTTON_MISC1},
};

View File

@@ -24,7 +24,7 @@ namespace InputCommon {
class SDLJoystick;
using ButtonBindings =
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 18>;
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 20>;
using ZButtonBindings =
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>;

View File

@@ -396,7 +396,7 @@ std::vector<Common::ParamPackage> UDPClient::GetInputDevices() const {
ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) {
// This list excludes any button that can't be really mapped
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 20>
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 22>
switch_to_dsu_button = {
std::pair{Settings::NativeButton::A, PadButton::Circle},
{Settings::NativeButton::B, PadButton::Cross},
@@ -412,8 +412,10 @@ ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& p
{Settings::NativeButton::R, PadButton::R1},
{Settings::NativeButton::ZL, PadButton::L2},
{Settings::NativeButton::ZR, PadButton::R2},
{Settings::NativeButton::SL, PadButton::L2},
{Settings::NativeButton::SR, PadButton::R2},
{Settings::NativeButton::SLLeft, PadButton::L2},
{Settings::NativeButton::SRLeft, PadButton::R2},
{Settings::NativeButton::SLRight, PadButton::L2},
{Settings::NativeButton::SRRight, PadButton::R2},
{Settings::NativeButton::LStick, PadButton::L3},
{Settings::NativeButton::RStick, PadButton::R3},
{Settings::NativeButton::Home, PadButton::Home},

View File

@@ -231,6 +231,7 @@ add_library(shader_recompiler STATIC
ir_opt/rescaling_pass.cpp
ir_opt/ssa_rewrite_pass.cpp
ir_opt/texture_pass.cpp
ir_opt/vendor_workaround_pass.cpp
ir_opt/verification_pass.cpp
object_pool.h
precompiled_headers.h

View File

@@ -559,12 +559,12 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
const IR::Value& offset, const IR::Value& lod_clamp) {
const auto info{inst.Flags<IR::TextureInstInfo>()};
ScopedRegister dpdx, dpdy, coords;
const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp};
const bool multi_component{info.num_derivatives > 1 || info.has_lod_clamp};
if (multi_component) {
// Allocate this early to avoid aliasing other registers
dpdx = ScopedRegister{ctx.reg_alloc};
dpdy = ScopedRegister{ctx.reg_alloc};
if (info.num_derivates >= 3) {
if (info.num_derivatives >= 3) {
coords = ScopedRegister{ctx.reg_alloc};
}
}
@@ -584,7 +584,7 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec,
dpdy.reg, derivatives_vec);
Register final_coord;
if (info.num_derivates >= 3) {
if (info.num_derivatives >= 3) {
ctx.Add("MOV.F {}.z,{}.x;"
"MOV.F {}.z,{}.y;",
dpdx.reg, coord_vec, dpdy.reg, coord_vec);

View File

@@ -548,15 +548,15 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
if (sparse_inst) {
throw NotImplementedException("EmitImageGradient Sparse");
}
if (!offset.IsEmpty() && info.num_derivates <= 2) {
if (!offset.IsEmpty() && info.num_derivatives <= 2) {
throw NotImplementedException("EmitImageGradient offset");
}
const auto texture{Texture(ctx, info, index)};
const auto texel{ctx.var_alloc.Define(inst, GlslVarType::F32x4)};
const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp};
const bool multi_component{info.num_derivatives > 1 || info.has_lod_clamp};
const auto derivatives_vec{ctx.var_alloc.Consume(derivatives)};
if (multi_component) {
if (info.num_derivates >= 3) {
if (info.num_derivatives >= 3) {
const auto offset_vec{ctx.var_alloc.Consume(offset)};
ctx.Add("{}=textureGrad({},{},vec3({}.xz, {}.x),vec3({}.yw, {}.y));", texel, texture,
coords, derivatives_vec, offset_vec, derivatives_vec, offset_vec);

View File

@@ -407,7 +407,7 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
}
ctx.AddCapability(spv::Capability::DemoteToHelperInvocation);
}
if (info.stores[IR::Attribute::ViewportIndex]) {
if (info.stores[IR::Attribute::ViewportIndex] && profile.support_multi_viewport) {
ctx.AddCapability(spv::Capability::MultiViewport);
}
if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) {

View File

@@ -84,6 +84,10 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
}
return std::nullopt;
case IR::Attribute::ViewportIndex:
if (!ctx.profile.support_multi_viewport) {
LOG_WARNING(Shader, "Ignoring viewport index store on non-supporting driver");
return std::nullopt;
}
if (ctx.profile.support_viewport_index_layer_non_geometry ||
ctx.stage == Shader::Stage::Geometry) {
return OutAttr{ctx.viewport_index, ctx.U32[1]};

View File

@@ -67,22 +67,22 @@ public:
}
}
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates, u32 num_derivates,
Id offset, Id lod_clamp) {
if (!Sirit::ValidId(derivates)) {
throw LogicError("Derivates must be present");
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives,
u32 num_derivatives, Id offset, Id lod_clamp) {
if (!Sirit::ValidId(derivatives)) {
throw LogicError("Derivatives must be present");
}
boost::container::static_vector<Id, 3> deriv_x_accum;
boost::container::static_vector<Id, 3> deriv_y_accum;
for (u32 i = 0; i < num_derivates; ++i) {
deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2));
deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2 + 1));
for (u32 i = 0; i < num_derivatives; ++i) {
deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2));
deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivatives, i * 2 + 1));
}
const Id derivates_X{ctx.OpCompositeConstruct(
ctx.F32[num_derivates], std::span{deriv_x_accum.data(), deriv_x_accum.size()})};
const Id derivates_Y{ctx.OpCompositeConstruct(
ctx.F32[num_derivates], std::span{deriv_y_accum.data(), deriv_y_accum.size()})};
Add(spv::ImageOperandsMask::Grad, derivates_X, derivates_Y);
const Id derivatives_X{ctx.OpCompositeConstruct(
ctx.F32[num_derivatives], std::span{deriv_x_accum.data(), deriv_x_accum.size()})};
const Id derivatives_Y{ctx.OpCompositeConstruct(
ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})};
Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y);
if (Sirit::ValidId(offset)) {
Add(spv::ImageOperandsMask::Offset, offset);
}
@@ -91,26 +91,26 @@ public:
}
}
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates_1, Id derivates_2,
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2,
Id offset, Id lod_clamp) {
if (!Sirit::ValidId(derivates_1) || !Sirit::ValidId(derivates_2)) {
throw LogicError("Derivates must be present");
if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) {
throw LogicError("Derivatives must be present");
}
boost::container::static_vector<Id, 3> deriv_1_accum{
ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 0),
ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 2),
ctx.OpCompositeExtract(ctx.F32[1], derivates_2, 0),
ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 0),
ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 2),
ctx.OpCompositeExtract(ctx.F32[1], derivatives_2, 0),
};
boost::container::static_vector<Id, 3> deriv_2_accum{
ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 1),
ctx.OpCompositeExtract(ctx.F32[1], derivates_1, 3),
ctx.OpCompositeExtract(ctx.F32[1], derivates_2, 1),
ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 1),
ctx.OpCompositeExtract(ctx.F32[1], derivatives_1, 3),
ctx.OpCompositeExtract(ctx.F32[1], derivatives_2, 1),
};
const Id derivates_id1{ctx.OpCompositeConstruct(
const Id derivatives_id1{ctx.OpCompositeConstruct(
ctx.F32[3], std::span{deriv_1_accum.data(), deriv_1_accum.size()})};
const Id derivates_id2{ctx.OpCompositeConstruct(
const Id derivatives_id2{ctx.OpCompositeConstruct(
ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})};
Add(spv::ImageOperandsMask::Grad, derivates_id1, derivates_id2);
Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2);
if (Sirit::ValidId(offset)) {
Add(spv::ImageOperandsMask::Offset, offset);
}
@@ -548,12 +548,12 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I
}
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id derivates, Id offset, Id lod_clamp) {
Id derivatives, Id offset, Id lod_clamp) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
const auto operands =
info.num_derivates == 3
? ImageOperands(ctx, info.has_lod_clamp != 0, derivates, offset, {}, lod_clamp)
: ImageOperands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, offset,
info.num_derivatives == 3
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp)
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset,
lod_clamp);
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],

View File

@@ -543,7 +543,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
const IR::Value& skip_mips);
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id derivates, Id offset, Id lod_clamp);
Id derivatives, Id offset, Id lod_clamp);
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color);
Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index);

View File

@@ -1864,11 +1864,11 @@ Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, Texture
return Inst(op, Flags{info}, handle, coords);
}
Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivates,
Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivatives,
const Value& offset, const F32& lod_clamp, TextureInstInfo info) {
const Opcode op{handle.IsImmediate() ? Opcode::BoundImageGradient
: Opcode::BindlessImageGradient};
return Inst(op, Flags{info}, handle, coords, derivates, offset, lod_clamp);
return Inst(op, Flags{info}, handle, coords, derivatives, offset, lod_clamp);
}
Value IREmitter::ImageRead(const Value& handle, const Value& coords, TextureInstInfo info) {

View File

@@ -335,7 +335,7 @@ public:
[[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset,
const U32& lod, const U32& multisampling, TextureInstInfo info);
[[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords,
const Value& derivates, const Value& offset,
const Value& derivatives, const Value& offset,
const F32& lod_clamp, TextureInstInfo info);
[[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info);
void ImageWrite(const Value& handle, const Value& coords, const Value& color,

View File

@@ -40,7 +40,7 @@ union TextureInstInfo {
BitField<21, 1, u32> has_lod_clamp;
BitField<22, 1, u32> relaxed_precision;
BitField<23, 2, u32> gather_component;
BitField<25, 2, u32> num_derivates;
BitField<25, 2, u32> num_derivatives;
BitField<27, 3, ImageFormat> image_format;
BitField<30, 1, u32> ndv_is_active;
};

Some files were not shown because too many files have changed in this diff Show More