[LINUX] Programmation de périphérique USB avec C natif sur Android 5.0 et supérieur

Je souhaite gérer les périphériques USB avec la bibliothèque C sur Android Lolipop ou version ultérieure

Depuis Lolipop, les appareils Android sont basés sur SELinux, il est donc un peu difficile de gérer les autorisations. Cet article décrit les points à noter lors de l'utilisation / l'écriture d'une bibliothèque en langage C qui gère les périphériques USB sur un terminal Android en tant qu'hôte USB.

Pourquoi le langage C?

Traditionnellement, les couches les plus proches des pilotes de périphériques sont principalement des bibliothèques écrites en C. Étant donné qu'Android est un dérivé de Linux, le pilote USB est le même en ce sens qu'il gère les usbfs, et fondamentalement une bibliothèque liée aux périphériques USB Linux peut être utilisée. Il n'est pas nécessaire de réinventer les roues en utilisant la bibliothèque USB unique d'Android.

Contraintes en C

Par exemple, libusb est une bibliothèque C qui gère les périphériques USB sur Android, mais [README] de libusb (https: // github. Si vous regardez com / libusb / libusb / blob / master / android / README), vous verrez ce qui suit.

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.

En effet, SELinux restreint l'accès sous / dev / bus / usb /, donc l'approche est écrite que vous devriez faire de votre mieux en donnant vous-même la permission. Ceci est correct lorsqu'il est considéré comme Android comme SELinux, mais ce n'est pas le cas pour la majorité des développeurs d'applications Android qui doivent développer sans privilèges root. Bien sûr, cette information seule est difficile à résoudre.

Procédure avec libusb etc.

Normalement, lors de l'utilisation de la bibliothèque C, le programme est le suivant.

  1. Ouvrez le port et récupérez le descripteur de fichier.
  2. Chargez le descripteur USB du périphérique à l'aide de l'imprimante de disque de fichiers. (Référence: SyncHack-USB / Descriptor)
  3. Identifiez l'interface USB ou le point de terminaison USB à partir du descripteur USB et communiquez avec le périphérique.

usb.c


const char* port_name = "/dev/bus/usb/000/001"; //périphérique USB(Cela change à chaque fois que vous vous connectez, donc effectuez une recherche, etc.)
int fd; //Imprimante de disque de fichiers
int rc;
int n_read;
byte[] desc; //Emplacement de stockage du descripteur USB

fd = open(port_name, 0_RDWR); //Port ouvert
...
rc = read(fd, desc, n_read); //Premier chargement du descripteur USB
...

Problèmes avec ce code-permissions

Ce code peut fonctionner sur les appareils Android sans aucun problème s'il peut être exécuté avec les privilèges root ou si l'appareil peut être personnalisé. Cependant, sur un terminal non root, l'ouverture d'un port provoque une erreur d'autorisation et ne fonctionne pas. Alors que devons-nous faire?

solution de contournement

Si vous suivez les étapes pour accéder à un périphérique USB sur le SDK Android, vous pouvez obtenir l'autorisation pour ce périphérique correctement. Comment accéder à un périphérique USB normalement sur le SDK Android est écrit dans USB Host of Developer Guide. Si vous suivez la procédure, vous pouvez l'obtenir sans aucun problème. Si vous n'utilisez pas la bibliothèque C, [ʻ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) Juste aller. Cependant, par exemple, même si ʻusb.c est exécuté après avoir exécuté ʻUSBManager # openDevice () , une erreur se produira. C'est parce qu'il y a en fait une imprimante de disque de fichiers émise à l'intérieur du SDK quand ʻopenDevice () est exécuté, et l'accès uniquement via cela est autorisé. Il n'est pas permis d'en ouvrir un nouveau et il est nécessaire d'utiliser uniquement l'imprimante de disque de fichiers. Le descripteur de fichier peut être obtenu avec ʻUsbDeviceConnection # getFileDescpritor () ](https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection.html#getFileDescriptor ()). Il existe également une [branche libusb](https://github.com/kuldeepdhaka/libusb/tree/android-open2) qui prend en charge cette "réutilisation des descripteurs de fichiers". Obtenu à partir du monde SDK en tant qu'argument de la fonction [ʻop_open2 () comme indiqué ci-dessous. Il est conçu pour vous donner un descripteur de fichier.

static int op_open2(struct libusb_device_handle *handle, int fd)

Autres problèmes-USB Descpritor

Maintenant, même si vous réutilisez l'imprimante de disque de fichiers, un autre problème se produira. Autrement dit, erreur d'E / S lors de la lecture de USB Descpritor. En fait, le SDK lit le Descpritor USB en même temps que ʻUSBManager # openDevice () , donc si vous réutilisez le preta du disque de fichiers, il a déjà été lu et vous ne pouvez pas le lire avec votre propre code. Alors, où est allé le descripteur USB chargé? [ʻUSBDeviceConnection # getRawDescpritors () ](https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection.html#getRawDescriptors ()) Il peut être retiré avec.

Formulaire rempli

Ainsi, il a été confirmé que si la bibliothèque C du périphérique USB est utilisée par la procédure suivante, la bibliothèque existante peut être utilisée tout en évitant le problème de permission et le problème de USB Descpritor.

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) { //Lors du contrôle par spécification du produit
    UsbDeviceConnection connection = manager.openDevice(device); //Ouvrir à ce stade(), read()Est en cours d'exécution.
    int fd = connection.getFileDescptitor(); //Imprimantes de disque de fichiers communicables autorisées par le SDK
    byte[] descpritors = connection.getRawDescpritors(); //Device, Configuration, Interface,Comprend tous les Descpritors tels que Endpoint
    callJNIUsbLib(fd, descpritors); //Il peut être traité en passant ces deux informations du côté JNI.
  }
}

Du côté de la bibliothèque C, l'implémentation devrait être "utiliser le fichier de disque au lieu d'ouvrir le fichier" et "utiliser celui qui a été passé sans acquérir le descpritor USB".

Recommended Posts

Programmation de périphérique USB avec C natif sur Android 5.0 et supérieur
Créez et exécutez Discord Bot sur un appareil Android
Programmation avec Python et Tkinter
Résolution avec Ruby et Python AtCoder ABC011 C Méthode de planification dynamique
Assembleur X86 sous Linux (lien avec C)
Un mémo contenant Python2.7 et Python3 dans CentOS
[C] [python] Lire avec AquesTalk sous Linux
Programmation normale avec la programmation Node-RED avec Raspberry Pi 3
Partager des listes de lecture VLC entre PC et Android
RaspberryPi L Chika avec Python et C #