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

Android Cannot Open device (hid_open) #178

Closed
DavEat opened this issue Jul 15, 2020 · 15 comments
Closed

Android Cannot Open device (hid_open) #178

DavEat opened this issue Jul 15, 2020 · 15 comments
Labels
Android Android OS related

Comments

@DavEat
Copy link

DavEat commented Jul 15, 2020

Hi,

I'm using .so libs of hidapi and libusb compile with linux for android
I have integrated those lib in a c++ project to make an interface to be able to call function in Java

(e.g. JNIEXPORT jint JNICALL Java_com_company_project_class_Enumerate(char* string, int length) //hid_enumerate
JNIEXPORT jint JNICALL Java_com_company_project_class_Open() //hid_open
(for now the vendorId and the productId are hard coded in the c++))

With hid_enumerate I have succeed to get some data from the devices such as the path or the vendorId
But if I try to use hid_open or hid_open_path it's always returning a nullptr hid_device*.

I should have set up my permission correctly (when I connect my hid device the phone ask me if I want to use the app I made with the usb device I just connect).

I also try to integrate it in Unity3d and I have the exact same behaviors.

Any help would be much appreciate since I'm completely block ATM.

@Youw
Copy link
Member

Youw commented Jul 15, 2020

The best what I can suggest right now - try to debug native calls (e.g. to libusb) and check its error-codes, to understand why the device cannot be opened.

@todbot
Copy link
Contributor

todbot commented Jul 15, 2020

Does your app have the correct permission filter in its AndroidManifest.xml and your code have the correct PendingIntent sent to UsbManager.requestPermission(device, permissionIntent)?
Here is an example USB HID device library for Android showing both, but using android.hardware.usb instead of hidapi.
https://github.com/todbot/blink1-android
You've gotten farther than I ever got getting hidapi working on Android, hopefully it's just a permissions problem.

@DavEat
Copy link
Author

DavEat commented Jul 18, 2020

For the permission I'm pretty sure they are ask correctly as I have an Android popup asking me if I want to grant permission to the app to use the USB.
But by digging in the hidapi and libusb code I found that in libusb_open (core.c line; 1315) the usbi_backend.open(_dev_handle); function return -3 with correspond to LIBUSB_ERROR_ACCESS (Access denied (insufficient permissions))
So I'm a bit confuse :/
As I said above I call hid_open(); from an .so lib.

Should I grant permission to hidapi instead of grant it to my app ? (I don't know if it's possible and how to do it).

@tuxun
Copy link

tuxun commented Jul 21, 2020

Are you trying to open the hid device using its linux device path instead of its device id? Its an easy mistake I made multiple time.

@DavEat
Copy link
Author

DavEat commented Jul 25, 2020

@tuxun I'm non sure to understand what you mean by device id as I'm using hid_open to find the path.
An example of path I receive when running on my android phone: dev/bus/usb/001/002.
Should I reformat the path or using an other function ?

hid.c (line 697)

int hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
{
        char* path_to_open = NULL;
	devs = hid_enumerate(vendor_id, product_id);
	cur_dev = devs;
	while (cur_dev) {
		...
        	path_to_open = cur_dev->path;
		...
		cur_dev = cur_dev->next;
        }
...
        hid_open_path(path_to_open);
...
}

@tuxun
Copy link

tuxun commented Jul 26, 2020

Hi,

From this post: #137 (comment)
Its seems hid_open_path doesnt work under android, we need to use hid_open(vendor_id, product_id, NULL);

Hoping it will help you

@DavEat
Copy link
Author

DavEat commented Jul 26, 2020

Hi,

we need to use hid_open(vendor_id, product_id, NULL);

that why I'm trying to do but in hidapi/libusb/hid.c the hid_open function essentially try to find the path of the device an the use it to call hid_open_path.

Does any one know or have an idea why libusb_open doesn't work on android ?

res = libusb_open(usb_dev, &dev->device_handle);

@tuxun
Copy link

tuxun commented Jul 26, 2020

"On Android hidapi is using libusb backend, and it doesn't operate with file-paths, but instead with USB entities, like "bus_number:device_address:interface_number", which makes a path, and it is a correct representation."

I think the answer is in there: hid_open_path

char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
					if (!strcmp(dev_path, path)) {
						/* Matched Paths. Open this device */

						/* OPEN HERE */
						res = libusb_open(usb_dev, &dev->device_handle);
						if (res < 0) {
							LOG("can't open device\n");
							free(dev_path);
							break;
						}

I would try something like hid_open("bus_number:device_address:interface_number"); as stated in the other answer i linked above.
@Youw could you have a look, please? That is what i understood from your answer 7 month ago, but i never tried it.

@Youw
Copy link
Member

Youw commented Jul 26, 2020

Its seems hid_open_path doesnt work under android, we need to use hid_open(vendor_id, product_id, NULL);

As was pointed by @DavEat, hid_open_path does work as much as hid_open, as it uses hid_open_path under the hood

I think the answer is in there: hid_open_path
make_path

This part is used only to identify corresponding libusb handle, which should be opened as a real device

I would try something like hid_open("bus_number:device_address:interface_number")

I wouldn't recommend anything like that.

  1. A path property from hid_device_info (from hid_enumerate) is preferable input for hid_open_path
  2. We have plans to change the representation of path for libusb backend

Does any one know or have an idea why libusb_open doesn't work on android ?

Well that's a good question.
res = libusb_open(usb_dev, &dev->device_handle);
@DavEat can you debug to this point and let me know what is the value of res when it fails?

if I'd need to guess, I'd say it either matches a wrong libusb device (on Android), or some kind of permissions issues

@mcuee mcuee added the Android Android OS related label Jul 29, 2020
@weiguanbu
Copy link

For the permission I'm pretty sure they are ask correctly as I have an Android popup asking me if I want to grant permission to the app to use the USB.
But by digging in the hidapi and libusb code I found that in libusb_open (core.c line; 1315) the usbi_backend.open(_dev_handle); function return -3 with correspond to LIBUSB_ERROR_ACCESS (Access denied (insufficient permissions))
So I'm a bit confuse :/
As I said above I call hid_open(); from an .so lib.

Should I grant permission to hidapi instead of grant it to my app ? (I don't know if it's possible and how to do it).

I'm having the same problem.
After I grant read and write permissions using 'chmod -R 777/dev/bus/usb', I can open the usb device normally, but only in the development environment with SU.

@mcuee
Copy link
Member

mcuee commented Jan 26, 2021

libusb/libusb#830
This pull request might help.

@mcuee
Copy link
Member

mcuee commented Jul 1, 2021

For Android users with libusb backend of HIDAPI, please check out libusb/libusb#830 which should work on unrooted Android device.

Yet the other new pull-request which may be even better is libusb/libusb#874 which is supposed to work with unrooted Android device "without user provided Java code".

@Youw
Copy link
Member

Youw commented Sep 30, 2021

After I grant read and write permissions using 'chmod -R 777/dev/bus/usb', I can open the usb device normally, but only in the development environment with SU.

Right, so I actually have a project that is using HIDAPI on Android un un-rooted device.

Android normally doesn't allow opening /dev/bus/usb/... devices directly. That is a part of its security implementation, etc.
So hid_open nor hid_open_path won't work on Android with Libusb backend as of this moment.
The only official way to get direct access to a USB device - is to use UsbManager, and yes, it is available only with Java API.

Essentially, to open a USB/HID device on Android, one must have some Java (or Jni) code that:

  1. Gets a list of all devices
  2. Finds the device that needs to be opened;
  3. Requests permission to use the device (a user will get a UI prompt, in case if it is a regular application);
  4. Open a device connection;
  5. Only then a native file descriptor (which should be passed to native code to be used with HIDAPI) can be used with newly introduced hid_libusb_wrap_sys_device;

So far I'm the only known to me user of hid_libusb_wrap_sys_device, and if more users try it/report bugs if any - I'll highly appreciate it.

@Youw
Copy link
Member

Youw commented Mar 12, 2023

My last message full describes the only possible workaround as of right now.

@Youw Youw closed this as completed Mar 12, 2023
@mcuee
Copy link
Member

mcuee commented Mar 12, 2023

Added the above comments to Wiki.
https://github.com/libusb/hidapi/wiki#faq

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android Android OS related
Projects
None yet
Development

No branches or pull requests

6 participants