mart1nro / joycontrol

Emulate Nintendo Switch Controllers over Bluetooth
GNU General Public License v3.0
1.24k stars 279 forks source link

connection dropped as soon as pair screen has been left #26

Open realquantumsource opened 4 years ago

realquantumsource commented 4 years ago

I was working on your code, and all of the sudden after what may have been dozens of successful pairs and tests I started getting this weird error every time I exited the pairing menu. I even made a new folder re cloned the repo and re installed the package, but I still have this joycontrol.transport_read::105 Error - No data received joycontrol.protocol connectyyion_lost::112 Error

I have attached two screens. I get the same error on both switches I don't know what I could have done to my ubuntu laptop system to have caused this to recur even on a clean clone. Please help if you can

Screenshot from 2020-04-17 17-31-46 Screenshot from 2020-04-17 17-32-18

JuanPotato commented 4 years ago

I wonder if this has anything to do with new switch update or the fix for that update. Has your switch updated to the 10.0 update?

realquantumsource commented 4 years ago

It has , but I have another switch on older version and it has the same issue. Also it was working for hours until I suspect an ubuntu update happened. The switch didn't change in that time

JuanPotato commented 4 years ago

You can check if an update has actually occurred if you open the /var/log/dpkg.log file. You should be able to see what changed and then find what broke.

realquantumsource commented 4 years ago

I even re formatted the hdd and reinstall from the same image I used a few months back, and it still failed, i'm guessing ubuntu did some kind of firmware change to my bluetooth chip or changed some bios setting I have no idea at this point why no matter what I do I can't leave (by any means) on any switch. Trying to get an image of ubuntu on my raspi now

JuanPotato commented 4 years ago

That's incredibly odd, I don't think Ubuntu would update the Bluetooth firmware unless you did a reboot. That may be possible then. May I ask what laptop you're running it on?

Could you open bluetoothctl in another terminal. Run joycontrol, and then put the full output of both joycontrol and bluetoothctl here?

mart1nro commented 4 years ago

Have you tried the reconnect option without opening the Change Grip/Order menu?

Maybe rather try Raspian on the pi instead of Ubuntu. There was an issue here where the connection didn't work with Ubuntu on the Raspberry Pi. It would probably require more setup.

Also someone also had the same issue that the connection dropped almost immediately and it worked once he used an usb Bluetooth adapter.

That does not explain why it was working before though.

realquantumsource commented 4 years ago

TO juanPotato's point I may have restarted the computer... I can't recall its a dell latitude 7480

And I did try the reconnect option too, get the exact same peer reset connection error. Downloading raspbian now, I'd use a usb adapter if I had one but amazon is slow.... lol hopefully this works on my pi3

Oh and JuanPotato, i'm getting the output from both app windows now

realquantumsource commented 4 years ago

I did a output capture of both devices before and after pressing home on the switch(or leaving the sync menu) joycontrol_beforeHome.txt Bluetoothctl-afterHome.txt Bluetoothctl-beforeHome.txt joycontrol_afterHome.txt

Quantum-Hui commented 4 years ago

I have the same issue on my jetson nano with an intel 8265AC wireless network adapter. But after adding an usb Bluetooth adapter, the connection goes well. Have no idea where the problem is. I was using a switch lite, haven't tried on a standard switch.

JuanPotato commented 4 years ago

I wonder if certain bluetooth modules just don't work well. I find it really odd that it disconnects after leaving the pairing page. @mart1nro Do you think it could have anything to do with certain bluetooth modules not allowing the ability to modify certain attributes? I don't even know if that is a thing, but if different bluetooth modules behave differently then I guess it might be

realquantumsource commented 4 years ago

Thats the only conclusion I can think of, and whats weird is it was working for many many reconnects then I took a break and when I came back (maybe after a system/firmware update it failed). I was/am working on a interpreter for the program to do time skips from shiney frames, and now a TASbot compiler for it. so good news/bad news, I got my program to work on my raspi3, but after a few minutes of button script it tends to skip or miss send a signal here and there which is a problem if every button press is key. I am playing with buffering teh waits a bit more

JuanPotato commented 4 years ago

I don't imagine a bluetooth connection would be the best in terms of precise input timing for TASbot.

realquantumsource commented 4 years ago

I see that now, and may turn my eyes to figuring out how to emulating in a similar way a usb controller. any recommendations are appreciated. THANKS to all for your help!

JuanPotato commented 4 years ago

I actually have already found a couple resources that may help you with this.

https://medium.com/better-programming/creating-a-fake-nintendo-switch-controller-to-level-up-my-character-in-world-of-final-fantasy-b50adc269a1e https://medium.com/@bertrandom/automating-zelda-3b37127e24c8

https://github.com/wchill/SwitchInputEmulator https://github.com/shinyquagsire23/Switch-Fightstick https://github.com/progmem/Switch-Fightstick https://github.com/ItsDeidara/CommunityController https://github.com/fossephate/switch-controller https://github.com/fluffymadness/ATMega32U4-Switch-Fightstick/

realquantumsource commented 4 years ago

I actually have already found a couple resources that may help you with this.

https://medium.com/better-programming/creating-a-fake-nintendo-switch-controller-to-level-up-my-character-in-world-of-final-fantasy-b50adc269a1e https://medium.com/@bertrandom/automating-zelda-3b37127e24c8

https://github.com/wchill/SwitchInputEmulator https://github.com/shinyquagsire23/Switch-Fightstick https://github.com/progmem/Switch-Fightstick https://github.com/ItsDeidara/CommunityController https://github.com/fossephate/switch-controller https://github.com/fluffymadness/ATMega32U4-Switch-Fightstick/

WOW man that's amazing, thanks so much

JuanPotato commented 4 years ago

You're welcome! Another thing to keep in mind is that you may not be able to get frame-perfect inputs even with these tools, so I leave you with one last link.

https://arstechnica.com/gaming/2020/01/inside-tasbots-semi-secret-probably-legal-effort-to-control-the-nintendo-switch/

I'm not sure how out of date this is, (it's only a few months old) but its something to keep in mind.

mart1nro commented 4 years ago

@mart1nro Do you think it could have anything to do with certain bluetooth modules not allowing the ability to modify certain attributes?

My guess is that some cheap bluetooth adapters aren't implemented well. But I'm also no expert in that regard.

SuperPichu commented 4 years ago

Interestingly I see this exact behavior on Debian 10 with both my Thinkpad x270 built-in bluetooth and my Gigabyte motherboard on my desktop's built-in bluetooth. Works fine with my $10 usb bluetooth though.

realkarmakun commented 4 years ago

Having the same issue with built-in Bluetooth module on lenovo ideapad 320, running EOS 5.1

s0r00t commented 4 years ago

Can confirm the issue with a Dell Latitude 7390 2-in-1 (8087:0a2b), which is called Intel Bluetooth Device. It seems to comes from the bundledIntel Corporation Wireless 8265 / 8275 (rev 78) chipset.

Issue is not present on a Lenovo ThinkPad X220 (0a5c:217f), which is a BCM2045B (BDC-2.1) from Broadcom.

JuanPotato commented 4 years ago

@s0r00t (or anyone else affected by this) Would you be willing to get a bluetooth wireshark capture while you connect to the switch and then leave the pair screen on both devices? It might help find what is causing the issue.

You can send the capture file to my email on my github profile.

s0r00t commented 4 years ago

I've sent you a dump via mail.

If any contributor needs it too, feel free to ask :)

jackz314 commented 4 years ago

I'm having the same issues, every time I leave the change grip/order page joycontrol disconnects with the error message

joycontrol.transport write::155 ERROR - [Errno 104] Connection reset by peer

Just a guess: Could this be caused by the MTU size limits on the PC/Bluetooth device? After looking at my Wireshark capture, it seems that all the packet sizes are at most 23 Bytes long, which is probably the default Linux limit or the Bluetooth device's limit. It's possible that Switch wants to use a larger MTU to communicate with the controllers after they're paired, therefore the connection drop due to different MTU sizes.

It is pretty weird though considering that it used to work perfectly and that it works in pairing mode.

Note: Switch uses BLE 4.1, which has a max MTU size of 512 bytes, and that's probably what they are using

jackz314 commented 4 years ago

Update: I tried using hciconfig to change the MTU to 512, but it doesn't seem to do anything, the packets are still at most 23 bytes.

JuanPotato commented 4 years ago

Yeah the packets are small and consistent just on their own

realquantumsource commented 4 years ago

I disabled my laptops bluetooth and got a bluetooth usb adapter (took a while to get from amazon) that fixed the problem I was having with disconnecting. The truly odd thing is I was using the same internal adapter for over a day without issue before it became one, I have to imagine something changed on my system to break it. If its a driver, or firmware I may never know

JuanPotato commented 4 years ago

It may be helpful for others in the future if we can make a list of known working usb adapters and known broken ones.

realquantumsource commented 4 years ago

I wanna try using a different flavor of linux (maybe I;ll make a live usb, any recommendations) and see if that makes a difference, it would confirm if its firmware or drivers/os modules

realquantumsource commented 4 years ago

Tried elemntery os 5.1.4 on live boot usb, and re cloned the project, it works fine, there is no disconect. SO its not device or firmware related, it may be driver or os related

JuanPotato commented 4 years ago

Could you get the linux kernel version uname -r and the bluez version bluetoothd -v on both OS's?

realquantumsource commented 4 years ago

So I just rebooted back into my normal ubuntu (dellinux 5.3.0-51 generic) and re enable the built in bluetooth from bios and re cloned the repo, I decided to see if It worked, it did. I have no idea if disabling the dive and re enabling it did it or if a newer version of the code fixed the issue, but I am up and running again with the same device and os that caused the issue the first time. BUt when I disconnected and tried again it failed again. investigating some stuff

realquantumsource commented 4 years ago

ok so it seems somehow I broke it again, even on liveusb... but when I have the app connect tro my switch on verison 3.0.0 it still works, and I can reconnect as much as I want with no issues. after doing that connection I still can't reconnect to my 10.0.2 switch, so maybe version 10 has something to do with it. Honestly I have no idea any more. But I do know that when I use the usb bluetooth device with the internal one disabled in bios I have no problems what so ever

jackz314 commented 4 years ago

Looking at this behavior of working first but stops working after a while, could this be related to whether the emulated controller is paired to the Switch? Maybe the Switch handles it differently when the controller is already paired, and in this part maybe joycontrol didn't handle something properly so the connection breaks? Just a guess.

Although it's still not working for me, perhaps someone else could try to isolate this issue by erasing the pairing history on the Switch and on Linux.

acriphonic commented 4 years ago

I also have this issue, although with a slightly different error message

cmd >> b [00:59:24] joycontrol.transport write::155 ERROR - [Errno 104] Connection reset by peer [00:59:24] joycontrol.protocol connection_lost::117 ERROR - Connection lost. [00:59:24] joycontrol.protocol input_report_mode_full::209 ERROR - [Errno 104] Connection reset by peer [00:59:24] __main__ _main::244 INFO - Stopping communication... Traceback (most recent call last): File "./run_controller_cli.py", line 268, in <module> _main(args) File "/usr/lib/python3.6/asyncio/base_events.py", line 484, in run_until_complete return future.result() File "./run_controller_cli.py", line 242, in _main await cli.run() File "/home/kmccarthy/joycontrol2/joycontrol/command_line_interface.py", line 190, in run await button_push(self.controller_state, *buttons_to_push) File "/home/kmccarthy/joycontrol2/joycontrol/controller_state.py", line 201, in button_push await controller_state.send() File "/home/kmccarthy/joycontrol2/joycontrol/controller_state.py", line 66, in send await self._protocol.send_controller_state() File "/home/kmccarthy/joycontrol2/joycontrol/protocol.py", line 68, in send_controller_state await self._controller_state_sender joycontrol.transport.NotConnectedError

I am on Ubuntu 18.04 LTS (not a VM) on an HP Spectre and was able to pair and repair successfully several times, until I rebooted my computer, and now I am encountering this issue for the first time. Kernel is 5.3.0-51-generic, bluetooth is 5.48.

I tried removing the Switch's pairing history, and a fresh checkout of the repo, but no luck, the issue is still occurring. I will try some other things.

I tried uninstalling and re-installing the associated packages, but no success there either.

acriphonic commented 4 years ago

I have done some further experimenting with some bizarre results. I have multiple laptops, and so far have been able to connect to my switch for only one session with each one, before encountering this issue. The first laptop I connected with was an Ubuntu 18.04 native installation, so I then tried using a Ubuntu 20.04 live USB and booting into that, but was unable to re-establish a connection. I took the same live USB, plugged it into my second laptop, and was again able to connect for one session to my switch. Worrying that I would lose the ability to connect to my switch again, I did not reboot, but by the time I tried again 2 days later, I was unable to connect to the switch. Rebooting into that same live USB, which would be considered a fresh machine every time, never did allow me to connect to the switch again a second time, which matches with my experience with the first laptop. I will try again with further laptops, but it is awfully strange that each laptop works only once, no matter whether the OS is fresh or not.

dpxcc commented 4 years ago

I'm having the same issue. Can confirm removing bluetooth history on both sides doesn't work. I'm wondering if changing bluetooth device address would help.

AntoineFaul commented 4 years ago

I'm having the same issue. It stopped working after I let my computer go to sleep mode with this error : cmd >> [14:48:05] joycontrol.transport write::155 ERROR - [Errno 104] Connection reset by peer [14:48:05] joycontrol.protocol connection_lost::117 ERROR - Connection lost. [14:48:05] joycontrol.protocol input_report_mode_full::209 ERROR - [Errno 104] Connection reset by peer

Running apt upgrade fixed the problem, but it came back the following day.

Those packages were upgraded :

Les NOUVEAUX paquets suivants seront installés : apt-config-icons apt-config-icons-hidpi linux-headers-5.4.0-40 linux-headers-5.4.0-40-generic linux-image-5.4.0-40-generic linux-modules-5.4.0-40-generic linux-modules-extra-5.4.0-40-generic Les paquets suivants seront mis à jour : accountsservice adwaita-icon-theme alsa-ucm-conf apparmor apport apport-gtk aptdaemon aptdaemon-data bind9-dnsutils bind9-host bind9-libs busybox-initramfs busybox-static curl dbus dbus-user-session dbus-x11 deja-dup desktop-file-utils eog evince evince-common evolution-data-server evolution-data-server-common file-roller firefox firefox-locale-en firefox-locale-fr fonts-opensymbol fwupd fwupd-signed gamemode gedit gedit-common gir1.2-accountsservice-1.0 gir1.2-freedesktop gir1.2-glib-2.0 gir1.2-gnomedesktop-3.0 gir1.2-gtk-3.0 gir1.2-mutter-6 gir1.2-nm-1.0 gir1.2-secret-1 gir1.2-vte-2.91 gjs glib-networking glib-networking-common glib-networking-services gnome-calendar gnome-control-center gnome-control-center-data gnome-control-center-faces gnome-desktop3-data gnome-initial-setup gnome-logs gnome-settings-daemon gnome-settings-daemon-common gnome-shell gnome-shell-common gnome-shell-extension-desktop-icons gnome-shell-extension-ubuntu-dock gnome-terminal gnome-terminal-data google-chrome-stable gtk-update-icon-cache initramfs-tools initramfs-tools-bin initramfs-tools-core intel-microcode libaccountsservice0 libapparmor1 libasound2 libasound2-data libatk-adaptor libatk-bridge2.0-0 libatopology2 libcamel-1.2-62 libcurl3-gnutls libcurl4 libdbus-1-3 libebackend-1.2-10 libebook-1.2-20 libebook-contacts-1.2-3 libecal-2.0-1 libedata-book-1.2-26 libedata-cal-2.0-1 libedataserver-1.2-24 libedataserverui-1.2-2 libegl-mesa0 libevdocument3-4 libevview3-3 libexif12 libfwupd2 libfwupdplugin1 libgamemode0 libgamemodeauto0 libgbm1 libgirepository-1.0-1 libgjs0g libgl1-mesa-dri libglapi-mesa libglib2.0-0 libglib2.0-bin libglib2.0-data libglx-mesa0 libgnome-desktop-3-19 libgnutls30 libgphoto2-6 libgphoto2-l10n libgphoto2-port12 libgtk-3-0 libgtk-3-bin libgtk-3-common libjpeg-turbo8 libjuh-java libjurt-java liblirc-client0 libmutter-6-0 libnautilus-extension1a libnetplan0 libnm0 libnss-systemd libnss3 libpam-systemd libproxy1-plugin-gsettings libproxy1-plugin-networkmanager libproxy1v5 libreoffice-base-core libreoffice-calc libreoffice-common libreoffice-core libreoffice-draw libreoffice-gnome libreoffice-gtk3 libreoffice-help-common libreoffice-help-en-us libreoffice-help-fr libreoffice-impress libreoffice-l10n-fr libreoffice-math libreoffice-ogltrans libreoffice-pdfimport libreoffice-style-breeze libreoffice-style-colibre libreoffice-style-elementary libreoffice-style-tango libreoffice-writer libridl-java libruby2.7 libseccomp2 libsecret-1-0 libsecret-common libsmbclient libsnmp-base libsnmp35 libsqlite3-0 libsystemd0 libudev1 libuno-cppu3 libuno-cppuhelpergcc3-3 libuno-purpenvhelpergcc3-3 libuno-sal3 libuno-salhelpergcc3-3 libunoloader-java libvncclient1 libvncserver1 libvte-2.91-0 libvte-2.91-common libwbclient0 libxatracker2 linux-base linux-firmware linux-generic-hwe-20.04 linux-headers-generic-hwe-20.04 linux-image-generic-hwe-20.04 linux-libc-dev login mesa-vulkan-drivers mutter mutter-common nautilus nautilus-data nautilus-extension-gnome-terminal netplan.io network-manager network-manager-config-connectivity-ubuntu openssh-client orca passwd python3-apport python3-aptdaemon python3-aptdaemon.gtk3widgets python3-distupgrade python3-problem-report python3-software-properties python3-uno python3-update-manager ruby2.7 samba-libs shotwell shotwell-common snapd software-properties-common software-properties-gtk systemd systemd-sysv systemd-timesyncd thermald thunderbird thunderbird-gnome-support thunderbird-locale-en thunderbird-locale-en-us thunderbird-locale-fr ubuntu-desktop ubuntu-desktop-minimal ubuntu-drivers-common ubuntu-minimal ubuntu-release-upgrader-core ubuntu-release-upgrader-gtk ubuntu-standard udev uno-libs-private update-manager update-manager-core ure wpasupplicant xserver-common xserver-xephyr xserver-xorg-core xserver-xorg-legacy xwayland yaru-theme-gnome-shell yaru-theme-gtk yaru-theme-icon yaru-theme-sound 234 mis à jour, 7 nouvellement installés, 0 à enlever et 0 non mis à jour.

sudofox commented 3 years ago

I'm running into the same, or similar issue. I was able to get the thing to pair one time and have it work, but trying to reconnect after that never works. I tried with a usb bluetooth adapter and that too worked but only once, it was unable to reconnect.

yellows8 commented 3 years ago

Figured out what causes disconnections triggered Switch-side. https://switchbrew.org/wiki/BTM_services#SetSlotMode https://switchbrew.org/wiki/Bluetooth_Driver_services#SetTsi

With a bt-device which triggers an error Switch-side with Mode Change Event, explicitly using command HCI_Sniff_Mode prior to that fixes it (and no more disconnections due to this). I'm not sure what the proper way to use that command is (with BlueZ/{...}). This is not needed with bt-devices which don't trigger that error.

Switch-side uses that command with the following parameters (at least in one case, not sure if the other ones are used):

Sniff Max Interval: 8 slots (5 msec)
Sniff Min Interval: 8 slots (5 msec)
Sniff Attempt: 1 (0.625 msec)
Timeout: 0 slots (0 msec)
JuanPotato commented 3 years ago

@yellows8 The only way I can find to use HCI_Sniff_Mode in bluez is to use sniff_mode_cp. That struct doesn't have an associated function so you need to make one like hci_exit_park_mode.

Related to this, I tried to figure out other bluetooth issues in the past but didn't make much progress. Like the lagging that happens when multiple devices are connected or disconnections happening after a long time. I don't know much about switch internals but I did notice the mode change event.

yellows8 commented 3 years ago

That requires the connection handle though, probably couldn't (?) use sockets with it. :/

Haven't checked how long it stays connected with Sniff Mode, other than verifying that the initial disconnect doesn't occur.

EvanGreener commented 3 years ago

I'm experiencing this issue too and Im using a raspberry pi 4b with the on board bluetooth. Im thinking of buying a bluetooth usb dongle, would any generic dongle work?

EvanGreener commented 3 years ago

That requires the connection handle though, probably couldn't (?) use sockets with it. :/

Haven't checked how long it stays connected with Sniff Mode, other than verifying that the initial disconnect doesn't occur.

How did you execute this HCI_Sniff_Mode command? Did you have to homebrew your switch or did you use something like hcitool in bluez?

yellows8 commented 3 years ago

How did you execute this HCI_Sniff_Mode command? Did you have to homebrew your switch or did you use something like hcitool in bluez?

Former can be done of course - the {not-proper-solution} uses a script which uses scapy: https://scapy.readthedocs.io/en/latest/layers/bluetooth.html

EvanGreener commented 3 years ago

How did you execute this HCI_Sniff_Mode command? Did you have to homebrew your switch or did you use something like hcitool in bluez?

Former can be done of course - the {not-proper-solution} uses a script which uses scapy: https://scapy.readthedocs.io/en/latest/layers/bluetooth.html

Where is said script?

yellows8 commented 3 years ago

How did you execute this HCI_Sniff_Mode command? Did you have to homebrew your switch or did you use something like hcitool in bluez?

Former can be done of course - the {not-proper-solution} uses a script which uses scapy: https://scapy.readthedocs.io/en/latest/layers/bluetooth.html

Where is said script?

It's part of {private stuff}, haven't bothered to extract the sniff-mode stuff into a dedicated script.

marcan commented 2 years ago

The sniff mode is getting canceled because Bluetooth sockets default to force-active mode, which will cancel sniff mode every time a packet is sent. This is what you want:

diff --git a/joycontrol/server.py b/joycontrol/server.py
index eb3e19a..b84531e 100644
--- a/joycontrol/server.py
+++ b/joycontrol/server.py
@@ -115,6 +115,12 @@ async def create_hid_server(protocol_factory, ctl_psm=17, itr_psm=19, device_id=
         client_ctl.setblocking(False)
         client_itr.setblocking(False)

+    # do not force active power (non-sniff mode)
+    SOL_BLUETOOTH = 274
+    BT_POWER = 9
+    client_ctl.setsockopt(SOL_BLUETOOTH, BT_POWER, 0)
+    client_itr.setsockopt(SOL_BLUETOOTH, BT_POWER, 0)
+
     # create transport for the established connection and activate the HID protocol
     transport = L2CAP_Transport(asyncio.get_event_loop(), protocol, client_itr, client_ctl, 50, capture_file=capture_file)
     protocol.connection_made(transport)

That fixes the disconnections.

JuanPotato commented 2 years ago

This is great, thanks @marcan! I'm yet to test this but do you know if it helps the issue where multiple controllers connected cause joycontrol to lag? #31

marcan commented 2 years ago

I have noticed the entire connection process is a lot more reliable/responsive with that set, so quite possibly. It seems it really doesn't like non-sniff mode.