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

scc-daemon drops existing USB devices when system suspends #57

Open
bell07 opened this issue Oct 28, 2024 · 9 comments
Open

scc-daemon drops existing USB devices when system suspends #57

bell07 opened this issue Oct 28, 2024 · 9 comments

Comments

@bell07
Copy link

bell07 commented Oct 28, 2024

Same issue like #55 but tested with current sc-controller-0.4.9.7-bookworm-x86_64.AppImage
If I suspend and resume system, the sc-controller does not work anymore

player@game-deck ~/Downloads $ ./sc-controller-0.4.9.7-bookworm-x86_64.AppImage daemon debug
D SCCDaemon     Starting SCCDaemon...
D SCCDaemon     Initializing drivers...
W SCCDaemon     Skipping disabled driver 'ds4drv'
W SCCDaemon     Skipping disabled driver 'ds5drv'
W SCCDaemon     Skipping disabled driver 'fake'
W SCCDaemon     Skipping disabled driver 'remotepad'
D USB           Registered USB driver for 28de:1102
D USB           Registered USB driver for 28de:1142
D USB           Registered USB driver for 28de:1205
D Mapper        Creating virtual devices
D Mapper        Keyboard: <scc.uinput.Keyboard object at 0x7f6a23d25e10>
D Mapper        Mouse:    <scc.uinput.Mouse object at 0x7f6a23d271d0>
D Mapper        Gamepad:  <scc.uinput.UInput object at 0x7f6a23d3a090>
D SCCDaemon     Created control socket /home/player/.config/scc/daemon.socket
D SCCDaemon     Connected to XServer :0.0
Exception in thread Thread-2 (_threaded):
Traceback (most recent call last):
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
Exception in thread Thread-3 (_threaded):
Traceback (most recent call last):
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    self.run()
    self.run()
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/threading.py", line 975, in run
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/site-packages/scc/sccdaemon.py", line 1443, in _threaded
    self._target(*self._args, **self._kwargs)
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/site-packages/scc/sccdaemon.py", line 1443, in _threaded
    self.p = subprocess.Popen(self.args, stdin=None)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/subprocess.py", line 1024, in __init__
    self.p = subprocess.Popen(self.args, stdin=None)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/subprocess.py", line 1024, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/subprocess.py", line 1901, in _execute_child
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/subprocess.py", line 1901, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/home/player/Downloads/usr/bin/python'
FileNotFoundError: [Errno 2] No such file or directory: '/home/player/Downloads/usr/bin/python'
D asyncio       Using selector: EpollSelector
D deck          Got SteamDeck with serial 3:3
D USB           USB device added: 28de:1205
D root          TODO: Hardcoded 1s sleep!
D SCCDaemon     Assigned default_mapper to <Deck deck3:3>
D SCCDaemon     Turning gyrosensor ON
D SCCDaemon     Controller added: <Deck deck3:3>
I CemuHook      Created CemuHookUDP Motion Provider
[..... system goes sleeping and wake up .... ]
Exception ignored on calling ctypes callback function: <bound method USBTransfer.__callbackWrapper of <class 'usb1.USBTransfer'>>
Traceback (most recent call last):
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3/dist-packages/usb1/__init__.py", line 328, in __callbackWrapper
    callback(self)
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3.11/site-packages/scc/drivers/usb.py", line 57, in callback_wrapper
    transfer.submit()
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3/dist-packages/usb1/__init__.py", line 748, in submit
    raiseUSBError(result)
  File "/tmp/.mount_sc-congtYQW1/usr/lib/python3/dist-packages/usb1/__init__.py", line 120, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorIO: LIBUSB_ERROR_IO [-1]
D root          TODO: Hardcoded 1s sleep!

Reopen issues seems to be disabled. I do not get the "Repopen" button :-( Therefore I created new issue

@C0rn3j
Copy link
Owner

C0rn3j commented Oct 28, 2024

Try https://github.com/C0rn3j/sc-controller/releases/tag/v0.4.9.8 although am not sure if it'll fix your issue.

@bell07
Copy link
Author

bell07 commented Oct 28, 2024

Still not solved.
The new error line appears, but crash is still there.

E USB           Failed to submit the transfer!
Traceback (most recent call last):
  File "/tmp/.mount_sc-conueE4qz/usr/lib/python3.11/site-packages/scc/drivers/usb.py", line 58, in callback_wrapper
    transfer.submit()
  File "/tmp/.mount_sc-conueE4qz/usr/lib/python3/dist-packages/usb1/__init__.py", line 748, in submit
    raiseUSBError(result)
  File "/tmp/.mount_sc-conueE4qz/usr/lib/python3/dist-packages/usb1/__init__.py", line 120, in raiseUSBError
    raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
usb1.USBErrorIO: LIBUSB_ERROR_IO [-1]
D root          TODO: Hardcoded 1s sleep!

I tried the next change with system installed old sc-controller:

                                try:
                                        transfer.submit()
                                except Exception as e:
                                        log.error("Failed to submit data")
                                        log.error(e)

This change get the python traceback away, but the inputs are not working after resume. My assumption is: Any kind of re-connection / re-initialization is needed to get the controls working again.

If I restart the daemon, the sc-controller is working again. (If I do it in /lib64/elogind/system-sleep/my-sleep.sh, the system freezes :-()

@C0rn3j
Copy link
Owner

C0rn3j commented Oct 28, 2024

Does it stop logging entirely afterwards, or does it keep working but just not with the previously connected devices?

i.e. you can connect a DS4 or whatever and it picks it up and works, but the USB devices it killed (or rather the Deck input itself?) remain dead until daemon restart?

Because the daemon should restart if it crashes to my understanding, this sounds like it just gets into a weird state.

Does it work if you add this to force restart the device in the exception I added?

				except Exception:
					log.exception("Failed to submit the transfer!")
					self.force_restart()

@bell07
Copy link
Author

bell07 commented Oct 28, 2024

The daemon is running. I see log entries and OSD messages, if I switch to other window with autoswicher configured.

Now I connected my Switch Pro controller trough USB and tried again. (sc-controller is able to handle multiple inputs ?!).
After resuming the switch controller does not work too. But if I remove the USB cable and attach again, the switch controller is working again.

If I add the self.force_restart() line, I loose both devices. Then the USB-Cable removal and attach does not help anymore.

Note: I still test with 0.4.8.17 because I do not know how I can launch sc-controller from source tree without installing

@C0rn3j
Copy link
Owner

C0rn3j commented Oct 28, 2024

I do not know how I can launch sc-controller from source tree without installing

Git clone it (.zip is currently broken) and ./run.sh or ./run.sh daemon to run just the daemon in debug mode.

The readme needs a bit of a touch up.

EDIT: Touched up.

sc-controller is able to handle multiple inputs ?!

Sigh, we really need a feature showcase.

If I add the self.force_restart() line, I lose both devices

Huh, any of these 4 methods work instead?

1.	self.flush()

2.	self.unclaim()

3.	self.close():

4.	self.resetDevice()
4.	self..close()

@bell07
Copy link
Author

bell07 commented Oct 29, 2024

All proposed commands does not help. I think the self.force_restart() is the right way. Played around with debug-prints. Found out using some debug-prints, the self.handle.close() does not return and is hanging. The process cannot be cancelled anymore and needs to be killed.

@C0rn3j
Copy link
Owner

C0rn3j commented Oct 29, 2024

I think there's another bug interfering here - where the daemon is just unable to handle a restart - this can be reproduced by running one version of the daemon, and then launching a DIFFERENT version of sc-controller.

That will attempt to restart the daemon, but it only kills it, it won't start its own no more.
Restarting sc-controller then lets it start its own daemon and it all works again.

@bell07
Copy link
Author

bell07 commented Oct 30, 2024

Updated the repository for last changes, cleared up and rebuild.
Removed the system-wide installed sc-controller

Tried again using './run.sh daemon --alone'
If I set self.force_restart() or self.handle.close(), the daemon is hanigin. CTRL-C cannot break, i need to kill -9 to cancel the process. :-(

My current adjustments:

$ git --no-pager diff 
diff --git a/run.sh b/run.sh
index 6455dfc..098c387 100755
--- a/run.sh
+++ b/run.sh
@@ -75,7 +75,8 @@ pip install --prefix ".env" dist/*.whl --force-reinstall
 if [[ ${1-} == 'daemon' ]]; then
 	# Kill any existing daemons before spawning our own
 	pkill -f scc-daemon || true
-	scc-daemon debug
+	shift
+	scc-daemon debug $@
 else
 	sc-controller $@
 fi
diff --git a/scc/drivers/steamdeck.py b/scc/drivers/steamdeck.py
index 04a80b0..8a4a70d 100644
--- a/scc/drivers/steamdeck.py
+++ b/scc/drivers/steamdeck.py
@@ -231,7 +231,7 @@ class Deck(USBDevice, SCController):
 		if self._ready:
 			self.daemon.remove_controller(self)
 			self._ready = False
-		USBDevice.close(self)
+		super().close()
 
 	def turnoff(self):
 		log.warning("Ignoring request to turn off steamdeck.")
diff --git a/scc/drivers/usb.py b/scc/drivers/usb.py
index 71cf1bc..3d422dd 100644
--- a/scc/drivers/usb.py
+++ b/scc/drivers/usb.py
@@ -57,7 +57,8 @@ class USBDevice(object):
 				try: # https://github.com/C0rn3j/sc-controller/issues/57
 					transfer.submit()
 				except Exception:
-					log.exception("Failed to submit the transfer!")
+					log.error("Failed to submit the transfer!")
+					self.force_restart()
 
 		transfer = self.handle.getTransfer()
 		transfer.setInterrupt(

EDIT: By the way, in the meantime the hid-steam kernel driver exists, that take the controller and gyro available in /dev/input/event*. How difficult is to change the steamdeck base from hidraw to hid or evdev? Maybe that is the direction to solve this issue ...

@C0rn3j
Copy link
Owner

C0rn3j commented Oct 31, 2024

How difficult is to change the steamdeck base from hidraw to hid or evdev?

No idea, never had to write a driver for this thing yet, but there are a bunch of existing ones you can take examples from, PlayStation controllers already do something similar I suppose.

Unfortunately no clue how to proceed here without spending a large amount of time learning libUSB and going through the codebase.

@C0rn3j C0rn3j changed the title System sleep crash scc-daemon drops existing USB devices when system suspends Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants