-
Notifications
You must be signed in to change notification settings - Fork 669
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
Termux (Android) support #285
Comments
This seems reasonable. Besides ctypes bindings for the Of the top of my mind I'm not sure where to place or how to name this interface. But are you willing to give it a shot and send me a patch/open a pull request? Archiving: original discussion on the libusb mailing list. |
Can do. But I was also not sure where to place this, as it is a different approach to the standard enumerate devices → select device to work with sequence. Would this be good:
I am also not sure whether this is only for Android or if we can natively get USB file descriptors on other systems from other programs? to work with... I have to check later but I think |
Do we need more detailed lib functions? class _LibUSB(usb.backend.IBackend):
# ...
# fd -> handle
@methodtrace(_logger)
def wrap_sys_device(self, sys_dev):
handle = _libusb_device_handle()
_check(self.lib.libusb_wrap_sys_device(self.ctx, sys_dev, byref(handle)))
return handle
# handle -> devid
@methodtrace(_logger)
def get_device(self, handle):
return self.lib.libusb_get_device(handle) Or how it most probably will only be used? class _FileDescriptorDeviceHandle(object):
def __init__(self, fd, ctx):
# get handle from file descriptor
self.handle = _libusb_device_handle()
_check(_lib.libusb_wrap_sys_device(ctx, fd, byref(self.handle)))
# get device (id?) from handle
self.devid = _lib.libusb_get_device(self.handle)
class _LibUSB(usb.backend.IBackend):
# ...
# fd --> dev (like _DeviceHandle)
@methodtrace(_logger)
def get_device_from_fd(self, fd):
return _FileDescriptorDeviceHandle(fd, self.ctx) I have not found a mention about the need to free the handles etc. Android libusb1 doc only mentions the creation of a temporary device... Working on it: master...Querela:master |
On my device: git clone https://github.com/Querela/pyusb.git && cd pyusb
python3 -m venv venv
source venv/bin/activate
pip install -e .
termux-usb -l
termux-usb -r -e ./tools/termux_device_info.py /dev/bus/usb/001/002
|
Last time I tested Termux and it does work with libusb (requires root) on my Android TV boxes. So yes it will be nice to see pyusb working under Termux. |
The output above works without root on my device (under Android 10). |
Great. I will try this when I have some time, probably over the weekend. Just notice that libusb was moved from termux-root-packages to the standard packages repo three months ago. |
Yes, I saw it only afterwards but I kind of remember that I saw the Termux issue some time ago when it was not yet implemented. Experiments etc.: |
@Querela could you publish tools/termux_device_info.py somewhere. I'm interested in adding support for --usb-fd for a cli that I've written for a tiqiaa IR blaster. |
😊 oops nm, I found it in your PR. |
Also note that if termux/termux-api#349 is fixed then no special handling for termux will be required in pyusb as the termux build of libusb will handle everything for you. |
Yes I can build libusb and pyusb under termux now without any changes. Running the test suite without real hardware seems to indicate no issues. But I have not tested with any real hardware devices yet. |
Related pull request: #287 |
ack. The core issue is that the default selinux configuration on newer Android versions doesn't allow direct access to /dev/bus/usb/ and a custom API has to be used to open usb devices (but once open it allows access to the file descriptor, which can be passed into libusb1 to use the device as normal). |
Please also refer to here about using current libusb Android support. |
And another one. |
ack, it looks like both of those only refer to accessing usb devices from within a java process that links to libusb. pyusb isn't going to be used in that way. I don't think pyusb is the right place to add support for Android, and that libusb should "do-it-all" (although some workarounds could be added in pyusb, until the time at which libusb fully supports Android). |
@normanr You are of course right. I think libusb/libusb#830 and libusb/libusb#874 are the right direction for libusb Android support. Please give them a try. The method in libusb pull request 830 is already usable now (it is just a README updates with an example). As for this particular patch, it covers a niche use cases for Termux users. I am actually using Termux myself and I do not really need to use the normal Android libusb support at all as I do now know Java/Android development myself and have no interests to know about either of them. (I am not a programmer myself but I know a little bit about C and Python). |
Unfortunately I tried https://github.com/Querela/pyusb/commits/master and it does not seem to work under my Huawei P20 running Android 10. The following two commands failed (hang). I simply do not have access to "/dev/bus/usb/" directory.
If I do not use the above two commands, it still failed.
|
I tried my Mi Box S Android TV box running Android TV OS 9.0 as well and "termux-usb -l" just does not list anything. So it seems to me that I do not have the right Android device to carry out the test. |
Then I used another Android 7 Box with root option (H96 Max RK3328 based box, need to run as root to have the write permissions), plain libusb/pyusb work as expected. However, termux-usb or tools/termux_device_info.py (from https://github.com/Querela/pyusb/blob/master/tools/termux_device_info.py) does not work. The error message is the same with root or without root.
|
All in all, it seems to me for #287 to work, "termux-usb -l" should work and it seems to me that means the right permission and existence of "/dev/bus/usb" which does not seem to be the case for my Android devices (non rooted). And this bridge seems to rely on a libusb fork. Technically you do not need to use a libusb fork as the latest libusb version should have the stuff in place already. But I think fundamentaly right now libusb needs a user provided helper (java) to work under Android non rooted device. The following libusb pull request is supposed to get rid of that user helper. |
termux_device_info.py accepts a file descriptor, not a path. When it's run via termux-usb the -e option will execute the specified command with a file descriptor referring to the device as its argument. You can not see the files because selinux does not allow it, only the java api's have access to the usb devices (and can be used open and return a file descriptor for them). So if you want to test without termux-usb (like on a non-android device), you need to do something like: The latest libusb does not have the right-stuff in place yet (as far as I know) to support opening usb devices on non-rooted devices without having to change the source code of the binary that you're using. #287 has the same problem (the source code of the binary needs to be changed to explicitly support reading the fd from the command line and opening it and giving it to libusb). libusb/libusb#874 doesn't get rid of the helper it just proposes to add some of the java glue required to get libusb working with non-rooted devices into libusb itself. It still requires the program that's opening the usb device to link to java and call the right init functions to make everything work. That only works for programs you have the source code to, and you're willing to change to make it work. The nice thing about AnotherTerm's helper is that it "just-works" for existing binaries. It could be nice to expose the wrap_sys_device API in pyusb, but it does require code changes to make use of it. I have some pending changes in a working tree, mostly the suggestions I made on #287, if you want I can look at committing and pushing them somewhere (not as a full PR, but so that they're not 100% lost). |
@normanr |
Not so sure if the patched libusb version will help. I will try it under Termux and unrooted Android. Ref: https://github.com/green-green-avk/AnotherTerm-scripts/blob/master/install-patched-libusb-1.0.23.sh |
Trying this, I get:
Any idea why Any ideas? Also were there any blockers for #287? |
You may need to put libusb-1.0.0.so in the right place in order for pyusb to work. Termux does not use the default location like |
I do not think #287 is ready. Please try it and post your test results. By right it should work with stock libusb-1.0.26 from termux and not a third party fork of libusb-1.0.23. And I think the right way to use libusb under Android is using the documented ways from libusb. I am not so sure how it can be adopted by Termux though as I do not know much about Android. There is also an on-going improvement for libusb under Android. |
Thanks, yeah I tried stuff like https://stackoverflow.com/a/71102974/2561747 to specify the location to no avail. But compiling stock libusb-1.0.23 worked, following this procedure termux/termux-packages#1714 (comment) but using the official release for version 1.0.23. I guess there may have been a backwards-incompatible change or regression since that version. But now the PR works and I can print device info, and read and write small bits of data. I keep getting timeout errors when writing large amounts of data (even with very long timeouts), but I'm not sure if that's from the pyusb fork or the application code. |
Hi,
In Termux you only receive a USB file descriptor (number bound to single process).
Any operations like
usb.core.find(..)
won't work.I wrote a workaround/fix that extends the libusb1 interface and provides the
Device
object given the file descriptor.See here: https://github.com/Querela/termux-usb-python/blob/e6166ded4555d988365e6609b91dec4f5ebb8fcd/usblib.py#L94
I only tested it on the most current Android (10) and Termux version ...
Usage examples are in my Repo.
Can we implement this in your library?
Enumerating devices would maybe work with subprocesses but working with a specific device is only possible in a process(?) callback and does not seem feasable. I guess ..?
The text was updated successfully, but these errors were encountered: