Skip to content

Conversation

@quaxalber
Copy link

Hey @HeuristicPerson

Thanks so much for your project. It helped me getting started. Since I needed to relay both keyboard and mouse , I decided to build my own solution on top. Feel free to pull if you like it.

Cheers

This was referenced Oct 11, 2023
@ig-sinicyn
Copy link

ig-sinicyn commented Nov 11, 2023

Hi!
@quaxalber , I've tried this version and I want to say a huge thanks for it! Works (almost) first try, no serious issues so far.

There are some minor ones. I cannot report them in the fork repo, so here it goes:

  1. For clean installation on RPi4 (lite os), there is no evdev module installed and the one in submodules does not work, no idea why. The bluetooth_2_usb.py -l fails something like "No module named 'evdev'" error. I cannot find exact message now but I may try to reproduce it if you're interested. Was workarounded with sudo apt install python3-evdev.
  2. Service does not start if keyboard or mouse is disconnected, it fails with FileNotFoundError. That's a pain if you use keyboard with multiple devices. Also, it looks like there is support for disconnected devices after service start but not at the startup time.
Output if no device connected

igors@hid-bridge:~/bluetooth_2_usb $ sudo python3.11 bluetooth_2_usb.py -k /dev/input/event2
23-11-11 21:40:56 [INFO] Launching Bluetooth 2 USB v0.4.4
23-11-11 21:40:58 [ERROR] Failed to initialize devices.
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 125, in __init__
    fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 80, in _init_devices
    self._create_and_register_links(keyboard_paths, mouse_paths)
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in _create_and_register_links
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in <listcomp>
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 148, in create_keyboard_link
    return self._create_device_link(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 167, in _create_device_link
    input_device = InputDevice(input_device_path)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 127, in __init__
    fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'
23-11-11 21:40:58 [ERROR] Houston, we have an unhandled problem. Abort mission.
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 125, in __init__
    fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 413, in <module>
    asyncio.run(_main())
  File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 386, in _main
    proxy = ComboDeviceHidProxy(args.keyboards, args.mice, args.sandbox)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 62, in __init__
    self._init_devices(keyboard_paths, mouse_paths, is_sandbox)
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 80, in _init_devices
    self._create_and_register_links(keyboard_paths, mouse_paths)
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in _create_and_register_links
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in <listcomp>
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 148, in create_keyboard_link
    return self._create_device_link(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 167, in _create_device_link
    input_device = InputDevice(input_device_path)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 127, in __init__
    fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'

@ig-sinicyn
Copy link

ig-sinicyn commented Nov 12, 2023

Okay, I've managed to workaround the second issue but the fix is really ugly.
I'm not a python dev and it works for me so I'd call it a day:)

@quaxalber
Copy link
Author

quaxalber commented Nov 14, 2023

Hey @ig-sinicyn

Thanks a lot for your feedback!

I was aware of both these issues. In fact the second one already had a dedicated issue in my fork. Cool that you figured out a solution yourself right away! Feel free to PR your fix so this one may be closed.

The first one got introduced when I switched from evdev PyPI package to my own submodule, since I wanted to be able to modify it. This one needs investigating why the submodule is not working properly. If you have a clue please let me know in this new issue!

I cannot report them in the fork repo,

Could you please explain? Do you mean my fork or yours?

Cheers

@ig-sinicyn
Copy link

ig-sinicyn commented Nov 14, 2023

Hi @quaxalber! :)

I'm really glad the feedback was well-received. The bridge works with no issues, no reboots or hiccups so far. The only thing I've noticed, the state of NumLock/CapsLock is not synchronised with device the RaspberryPi is attached to. I've did not investigated it deeper so far so I'm not sure where the real problem is. It may be my device, raspberry, my keyboard or all of them:)

Could you please explain? Do you mean my fork or yours?

Well, it was my fault:) I've refreshed your's fork page and the issues tab appeared. I thought there's no issues for the forks, my bad.

@ig-sinicyn
Copy link

Feel free to PR your fix so this one may be closed.

I'll try but I canot promise when. Had a pretty busy week

@quaxalber
Copy link
Author

I'll try but I canot promise when. Had a pretty busy week

No worries at all. Any time you like.

NumLock/CapsLock is not synchronised with device

Hmm weird. Works fine for me with Win 11 & Linux. What's your OS? Have you tried debugging with -d flag?

quaxalber and others added 30 commits December 13, 2023 22:41
* Use asyncio.all_tasks() again to check if relay is active

* Add missing type hints

* Add Arguments class with typed properties

* Reformat help texts

* Unify punctuation

* Print help arg last

* Re-add print_help()

* Rearrange help args

* Update docs to v0.7.1

* Bump version
* Add Arguments.__str__()

* Move arg setup to CustomArgumentParser
* Add Arguments.__str__()

* Move arg setup to CustomArgumentParser

* Fix object representations
Fix type hints

* Fix variable name

* Fix relay str representation

* Bump version

* Run git fetch before tag

* Log signal name instead of int on shutdown

* Re-add sys.exit(0) in signal handler
* Make venv dir non-hidden
* Fix device representation

* Remove str cast

* Fix debug output

* Bump version
* Update docs to v0.7.4
* Build Arguments.__str__() dynamically

* Update docs
* Move intro to top

* Specify RPi OS as mandatory requirement

* Specify RPi OS Bookworm

* Add link to RPi OS Bookworm blog post
* Clean up DeviceIdentifier

* Add missing imports
* Set new overview image

* Update overview image license
* Choose correct config.txt

* Load kernel modules

* Make sure dtoverlay is added under [all]

* Remove redundant module loading

* Check if dir and links exist

* Change log color

* Bump version
* Remove executor when relaying events

* Use boot mouse gadget

* Add udev monitor to register device changes

* Adapt logging
* Move init_usb_gadgets to controller

* Exclude vc4-hdmi devices

* Use dict to track tasks

* Use ContextManager for DeviceRelay

* Handle blocked gadgets

* Use ContextManager for UdevEventMonitor

* Add error handling

* Improved shutdown logic

* Add type hints

* Adapt logging

* Introduce UsbHidManager

* Use shutdown event

* Exit with code 1 on error

* Update docs
* Create PyPI-publish.yml

* Delete .github/workflows/python-publish.yml
…130)

* Implement interrupt shortcut

* Change log level on (un)grab failure

* Set grabbed flag on context init

* Use find_key_name()

* Update docs
* Implement UDC state monitor

* Set default interrupt shortcut

* Release all buttons on shortcut trigger

* Rename relay_active_event

* Make ContextManagers async

* Remove unused imports

* Remove unnecessary code

* Adapt logging 

* Update docs
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

Successfully merging this pull request may close these issues.

3 participants