hidapi icon indicating copy to clipboard operation
hidapi copied to clipboard

Android Cannot Open device (hid_open)

Open DavEat opened this issue 5 years ago • 13 comments

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.

DavEat avatar Jul 15 '20 15:07 DavEat

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.

Youw avatar Jul 15 '20 16:07 Youw

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.

todbot avatar Jul 15 '20 16:07 todbot

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).

DavEat avatar Jul 18 '20 11:07 DavEat

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.

tuxun avatar Jul 21 '20 20:07 tuxun

@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);
...
}

DavEat avatar Jul 25 '20 09:07 DavEat

Hi,

From this post: https://github.com/libusb/hidapi/issues/137#issuecomment-576664696 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

tuxun avatar Jul 26 '20 09:07 tuxun

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 ? https://github.com/libusb/hidapi/blob/ca1a2d6efae8d372587f4c13f60632916681d408/libusb/hid.c#L906

DavEat avatar Jul 26 '20 09:07 DavEat

"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.

tuxun avatar Jul 26 '20 10:07 tuxun

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

Youw avatar Jul 26 '20 22:07 Youw

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.

weiguanbu avatar Aug 04 '20 07:08 weiguanbu

https://github.com/libusb/libusb/pull/830 This pull request might help.

mcuee avatar Jan 26 '21 02:01 mcuee

For Android users with libusb backend of HIDAPI, please check out https://github.com/libusb/libusb/pull/830 which should work on unrooted Android device.

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

mcuee avatar Jul 01 '21 07:07 mcuee

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 avatar Sep 30 '21 11:09 Youw

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

Youw avatar Mar 12 '23 13:03 Youw

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

mcuee avatar Mar 12 '23 13:03 mcuee