Android Cannot Open device (hid_open)
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.
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.
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.
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).
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 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);
...
}
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
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
"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.
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.
- A
pathproperty fromhid_device_info(fromhid_enumerate) is preferable input forhid_open_path - We have plans to change the representation of
pathfor libusb backend
Does any one know or have an idea why
libusb_opendoesn'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
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.
https://github.com/libusb/libusb/pull/830 This pull request might help.
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".
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:
- Gets a list of all devices
- Finds the device that needs to be opened;
- Requests permission to use the device (a user will get a UI prompt, in case if it is a regular application);
- Open a device connection;
- 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.
My last message full describes the only possible workaround as of right now.
Added the above comments to Wiki. https://github.com/libusb/hidapi/wiki#faq