Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor GCAdapter, part 1 #10604

Merged
merged 14 commits into from Jun 4, 2022
Merged

Conversation

Pokechu22
Copy link
Contributor

In particular, the android and non-android versions are now in a single file, with the parts where they differ separated using the preprocessor. I also removed some old special cases, which may or may not be relevant.

I don't own a GC adapter, so this PR has not been tested at all (and thus I'm submitting it as a draft). Further work will probably be done as a separate PR.

@Pokechu22
Copy link
Contributor Author

@Pokechu22 Pokechu22 force-pushed the gcadapter-refactor branch 2 times, most recently from 76a12e2 to 6f0d855 Compare April 23, 2022 20:33
@pizuz
Copy link

pizuz commented Apr 24, 2022

Working fine on macOS Catalina x86_64.

@shuffle2
Copy link
Contributor

tbh i think splicing 2 files into 1 with a bunch of #ifdefs is a step backward.

@Pokechu22
Copy link
Contributor Author

I think the current 2-file version with large amounts of overlapping code is pretty bad, especially since the different files diverged for various bugfixes and other behaviors. But it would make sense to eventually split out the libusb and android code into other files, once everything else is merged nicely.

Code like

#ifndef ANDROID
  if (s_handle == nullptr)
    return;
#else
  if (!s_detected || !s_fd)
    return;
#endif

is something that I wouldn't want to keep permanently, but is a bit awkward to merge together.

(I'm also not sure what the deal is with s_fd on android, as it's obtained from Java code, but then the value is never sent back to the Java code or used for any IO operations - it seems like it's effectively just treated as a (redundant?) boolean flag.)

@jordan-woyak
Copy link
Member

The ifdefs are unfortunate but better than completely separate files. At least the duplicate code is merged.

Ideally I think we'd want an interface for the basic libusb functionality with Android/PC implementations.

@JMC47
Copy link
Contributor

JMC47 commented May 22, 2022

This fixes LibUSB issues on certain hardware, so we should probably get this cleaned up and reviewed.

@JaredWhiteOne
Copy link

Tested on Windows with the Super Smash Bros. GameCube Adapter for Wii U and MAYFLASH 2 Ports Wii U GC GameCube Controller Adapter for Wii U/PC. Adapter was detected in settings and controller was working as intended.

@Pokechu22 Pokechu22 marked this pull request as ready for review May 23, 2022 05:27
@Pokechu22
Copy link
Contributor Author

I've got an adapter now and have done some testing, and things seem good on Windows at least. I still need to test on Android, though.

@pizuz
Copy link

pizuz commented May 23, 2022

Tested again on macOS Catalina. Adapter working as it should.

@Pokechu22
Copy link
Contributor Author

I did some testing with the CI build on android, and it seems to work fine there too (although it was a debug build so performance wasn't great). This PR is ready for review.

@JMC47
Copy link
Contributor

JMC47 commented Jun 1, 2022

This build works fine for me on windows and Android, forgot to comment.

@iwubcode
Copy link
Contributor

iwubcode commented Jun 1, 2022

Need to look over the exit-early commit some more, not super familiar with the input code but from what I could tell all seems like a solid refactor.

@Pokechu22
Copy link
Contributor Author

That commit's easier to look at if you disable whitespace (git show -w or ?w=1 in the GitHub URL: b69b579?w=1)

@iwubcode
Copy link
Contributor

iwubcode commented Jun 1, 2022

Ah neat, did not know that was a thing. That is much easier to read!

Copy link
Contributor

@Dentomologist Dentomologist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not done reviewing but wanted to make some comments in case I didn't finish. Mostly nitpicky except for casting the type byte for each controller.

#ifndef ANDROID
#include <libusb.h>
#else
#include <jni.h>
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] I think if-else statements are slightly easier to follow when the condition is positive:

#ifdef ANDROID
#include <jni.h>
#else
#include <libusb.h>
#endif

There are a few similar occurrences I would swap, if I'm not missing a reason to do it this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mostly trying to put the non-android code on the top (though there isn't a strong reason for doing so). I could add a second define for using the libusb implementation instead, or I could just swap them. Do you have any preference between these?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost called this out as well. I agree about the positiveness being more readable though I also feel like if statements are easier to read if the smaller block is on top.

As for using a second define or swap them, I don't personally have a preference.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the long run I don't think it really matters because the plan is to split the android USB code and the libusb code into separate files again in a later PR (leaving the common logic in GCAdapter), so it doesn't really matter which comes first. I'll swap them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... actually, while trying to swap them, I've found that there are a lot of cases where it's #ifndef ANDROID without a corresponding #else (at least initially), so a second define is probably better (otherwise it'll just end up being a mix of #ifdef ANDROID and #ifndef ANDROID which is much more confusing than almost entirely #ifndef ANDROID).

Source/Core/InputCommon/GCAdapter.cpp Outdated Show resolved Hide resolved
int err = libusb_interrupt_transfer(s_handle, s_endpoint_in, s_controller_payload_swap,
int err = libusb_interrupt_transfer(s_handle, s_endpoint_in, s_controller_payload_swap.data(),
sizeof(s_controller_payload_swap), &payload_size, 16);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

err can be const.

[Opinion/Bikeshed] Not that I expect anyone to be confused by err, but in the spirit of updating unnecessarily abbreviated names from old code this could be error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I've also added a new fmt::formatter that calls libusb_strerror and libusb_error_name to improve the related log messages.

static u8 s_controller_payload[37];
static u8 s_controller_payload_swap[37];
static std::array<u8, 37> s_controller_payload;
static std::array<u8, 37> s_controller_payload_swap;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since _swap and _copy are defined to have the same size as _payload, would it make sense to make that explicit with std::array<u8, s_controller_payload.size()>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create constexpr size_t CONTROLER_PAYLOAD_SIZE = 37 instead.

// TODO: What do the other bits here indicate? Does casting to an enum like this make sense?
const auto type = static_cast<ControllerType>(controller_payload_copy[1 + (9 * chan)] >> 4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen any explicit documentation on the adapter's protocol, so flagging this for anybody who knows it better.

From what I can tell everything else assumes 0 <= type <= 2 which implies the top two bits are 0. If that's not necessarily the case we need to deal with that somehow.

@Pokechu22 Pokechu22 force-pushed the gcadapter-refactor branch 6 times, most recently from b27075c to bcb5969 Compare June 2, 2022 22:38
@@ -87,10 +87,14 @@ static std::array<u8, SerialInterface::MAX_SI_CHANNELS> s_controller_type = {
ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE};
static std::array<u8, SerialInterface::MAX_SI_CHANNELS> s_controller_rumble{};

constexpr size_t CONTROLER_INPUT_PAYLOAD_EXPECTED_SIZE = 37;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to move these above their respective usages (at least until there are extra scenarios where they are used) so as to improve readability?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're already used in several places (both for declaring the variables and when reading into them), and IMO it's better to have them all together to highlight that the sizes are different (and that different sizes are used for rumble and init).

Copy link
Contributor

@iwubcode iwubcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Untested. LGTM

This is mostly a brainless merge, #ifdef-ing anything that doesn't match between the two while preserving common logic.  I didn't rename any variables (although similar ones do exist), but I did change one log that was ERROR on android and NOTICE elsewhere to just always be NOTICE.  Further merging will follow.
I believe the setting already existed in the UI; it just wasn't implemented in GCAdapter_Android.cpp.
This hack was added in 8f0cbef, and the part of it in SI_DeviceGCAdapter is present on Android already, so I don't see any reason why this part doesn't apply to Android.
It was removed for non-android in 56239d1, and android already uses a separate thread, so presumably this isn't needed anymore.
This is only so that indentation is consistent with the non-android code.
@JMC47 JMC47 merged commit 664663e into dolphin-emu:master Jun 4, 2022
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
8 participants