Since Lolipop, Android devices are based on SELinux, so it's a little difficult to handle Permission. This article describes the points to note when using / writing a library in C language that handles USB devices on an Android device as a USB host.
Traditionally, the layers closer to device drivers are mostly libraries written in C. Since Android is a derivative of Linux, it is the same in that it handles usbfs for USB drivers, and basically you can use libraries related to Linux USB devices. There is no need to reinvent the wheel using Android's unique USB library.
For example, libusb is a C library that handles USB devices on Android, but libusb's [README](https://github. If you look at com / libusb / libusb / blob / master / android / README), you will see the following.
The default system configuration on most Android device will not allow access to USB devices. There are several options for changing this.
If you have control of the system image then you can modify the ueventd.rc used in the image to change the permissions on /dev/bus/usb//. If using this approach then it is advisable to create a new Android permission to protect access to these files. It is not advisable to give all applications read and write permissions to these files.
For rooted devices the code using libusb could be executed as root using the "su" command. An alternative would be to use the "su" command to change the permissions on the appropriate /dev/bus/usb/ files.
Users have reported success in using android.hardware.usb.UsbManager to request permission to use the UsbDevice and then opening the device. The difficulties in this method is that there is no guarantee that it will continue to work in the future Android versions, it requires invoking Java APIs and running code to match each android.hardware.usb.UsbDevice to a libusb_device.
Indeed, SELinux restricts access under / dev / bus / usb /
, so the approach is written that you should do your best by giving permission yourself. This is correct when viewed as Android as SELinux, but it is out of focus for the majority of Android app developers who have to develop without root privileges. Of course, this information alone is difficult to solve.
Normally, when using the C library, the program is as follows.
usb.c
const char* port_name = "/dev/bus/usb/000/001"; //USB device(It changes every time you connect, so actually search etc.)
int fd; //File disk printer
int rc;
int n_read;
byte[] desc; //Storage location of USB Descriptor
fd = open(port_name, 0_RDWR); //Port open
...
rc = read(fd, desc, n_read); //First loading of USB Descriptor
...
This code works fine on Android devices as long as you can run it with root privileges or customize your device. However, on a non-root terminal, opening a port causes a permission error and it does not work. Then what should we do?
If you follow the steps to access a USB device on the Android SDK, you can get permission to the device properly. How to get access to a USB device normally on the Android SDK is described in USB Host of Developer Guide. If you follow the procedure, you can get it without any problem. If you don't use the C library, [ʻUsbManager](https://developer.android.com/reference/android/hardware/usb/UsbManager.html), [ʻUsbDevice
](https://developer. android.com/reference/android/hardware/usb/UsbDevice.html), [ʻUsbDeviceConnection](https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection.html) Just go. However, for example, even if you execute the above ʻusb.c
after executing ʻUSBManager # openDevice (), an error will occur. This is because there is actually a file disk printer issued inside the SDK when ʻopenDevice ()
is executed, and access only via that is permitted. It is not allowed to open a new file, and it is necessary to use only the file disk printer. The file descriptor can be obtained with ʻUsbDeviceConnection # getFileDescpritor () ](https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection.html#getFileDescriptor ()). There is also a [libusb branch](https://github.com/kuldeepdhaka/libusb/tree/android-open2) that supports this "reuse of file disk preta". Get from the SDK world to the argument of the function [ʻop_open2 ()
as below It is designed to give a file descriptor.
static int op_open2(struct libusb_device_handle *handle, int fd)
Now, even if you reuse the file disk printer, another problem will occur. That is, I / O error occurs when reading the USB Descpritor. Actually, the SDK reads the USB Descpritor at the same time as ʻUSBManager # openDevice (), so if you reuse the file disk preta, it has already been read and you cannot read it with your own code. So where did the loaded USB Descriptor go? [ʻUSBDeviceConnection # getRawDescpritors ()
](https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection.html#getRawDescriptors ()) It can be taken out with.
So, it was confirmed that if the C library of the USB device is used by the following procedure, the existing library can be used while avoiding the permission problem and the USB Descpritor problem.
Usb.java
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
for(UsbDevice device : deviceList.values()) {
if(device.getVenforId() == 0xZZ && device.getProductId() == 0xYY) { //When controlling by product specification
UsbDeviceConnection connection = manager.openDevice(device); //Open at this point(), read()Is being executed.
int fd = connection.getFileDescptitor(); //Communicatable file disk printers allowed by the SDK
byte[] descpritors = connection.getRawDescpritors(); //Device, Configuration, Interface,Includes all Descpritors such as Endpoint
callJNIUsbLib(fd, descpritors); //It can be processed by passing these two pieces of information to the JNI side.
}
}
On the C library side, the implementation should be "use the file disk pretter instead of opening the file" and "use the one passed without acquiring the USB Descpritor".
Recommended Posts