Lire Felica en utilisant RC-S380 (PaSoRi) en Java

Aperçu

Je veux utiliser PaSoRi autre que Windows! Quand j'y pense, je pense que le nfcpy de Python est le premier choix, mais je veux le faire avec Java au lieu de Python! À ce moment-là, je n'ai pas pu trouver l'exemple de code (ou presque tous les exemples Python ... !!), alors j'aimerais résumer le processus jusqu'au point où il fonctionne.

référence

Comme référence tout d'abord, j'ai beaucoup fait référence à l'article suivant. Je suis reconnaissant aux ancêtres qui l'ont mis en œuvre car je ne peux pas obtenir les spécifications, etc. à moins que je ne l'achète en tant que société.

Un bref résumé de la gestion de l'USB à partir de Java

Les projets suivants semblent nouveaux et prospères, je les adopterai donc sans penser à rien. http://usb4java.org/

En regardant le site, il semble qu'il existe des API de bas niveau (libusb) et de haut niveau (javax.usb), et cette fois, ce sera plus facile à comprendre, alors j'ai essayé d'utiliser javax.usb. Dans ce cas, la page suivante sera très utile.

La procédure normale pour accéder à un périphérique USB à l'aide de l'API JSR-80 est la suivante:

  1. Obtenez les UsbServices appropriés de UsbHostManager et bootstrap.
  2. Accédez au hub racine avec les services Usb. Le hub racine est considéré comme UsbHub dans l'application.
  3. Obtenez une liste des UsbDevices connectés au hub racine. Examinez tous les hubs de niveau inférieur pour trouver le bon UsbDevice.
  4. Utilisez le message de contrôle (UsbControlIrp) pour communiquer directement avec le UsbDevice, ou demandez l'UsbInterface à partir de l'UsbConfiguration appropriée sur l'UsbDevice et effectuez les E / S en utilisant UsbEndpoint disponible sur UsbInterface.
  5. Si UsbEndpoint est utilisé pour effectuer des E / S, ouvrez le UsbPipe associé. Les données en amont (périphérique USB vers ordinateur hôte) et les données en aval (ordinateur hôte vers périphérique USB) sont soumises de manière synchrone ou asynchrone par UsbPipe.
  6. Fermez UsbPipe et libérez l'interface Usb appropriée si l'application n'a plus besoin d'accéder à UsbDevice.

Sur la base de l'article ci-dessus, un bref résumé de la procédure de communication

  1. Détectez l'USB à partir de l'ID fournisseur et de l'ID produit. Chaque ID est publié de manière unique (devrait). Par exemple, dans le cas de ce RC-S380, l'ID du fournisseur est 0x054C, l'ID du produit est 0x06C3 ..
  2. De là, obtenez Configuration, Interface, Endpoint. En outre, il existe deux endroits où Endpoint échange réellement des données lors de la communication avec USB, vers l'intérieur et vers l'extérieur par rapport à USB.
  3. Envoyez une communication arbitraire à l'appareil et recevez une réponse

Comme mentionné ci-dessus, ce n'est pas une procédure si difficile tant que vous connaissez la commande de contrôle de l'appareil.

Entraine toi

Détection de périphérique

Étant donné que l'USB peut être connecté dans un format arborescent avec un hub, il est nécessaire de rechercher l'USB dans un style Imozuru et de trouver l'USB souhaité. Vous pouvez obtenir l'itinéraire virtuel ci-dessous.

RCS380.java


UsbServices services = UsbHostManager.getUsbServices();
UsbHub rootHub = services.getRootUsbHub();

Recherchez ensuite l'appareil par le fournisseur et l'ID de produit que vous avez recherchés précédemment. Voici l'exemple. Recherche récursive même s'il y a un hub au milieu.

RC380.java


public UsbDevice findDevice(UsbHub hub, int vendorId, int productId) throws UsbException, UnsupportedEncodingException {
        for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices()) {
            UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();

            if (desc.idVendor() == vendorId && desc.idProduct() == productId) return device;
            if (device.isUsbHub()) {
                device = findDevice((UsbHub) device, vendorId, productId);
                if (device != null) return device;
            }
        }
        return null;
    }

La détection des appareils est facile!

Je voulais dire ..., mais il y a un point auquel j'étais accro personnellement ici, et si je continue comme ça, la configuration n'est pas active, donc je suis tombé dans une situation où UsbPipe pour échanger à Endpoint 2 ne pouvait pas être ouvert. C'était. J'ai vérifié s'il existe une méthode pour setConfiguration ou activateConfiguration avec javax, mais je ne l'ai pas trouvée, donc pour plus tard, je définirai la configuration à l'aide de l'API de bas niveau (libusb) uniquement à un endroit ici.

//javax.usb.*Si c'est juste, la configuration n'est pas active, alors activez la configuration avec LibUSB ...
DeviceHandle dh = LibUsb.openDeviceWithVidPid(null, (short) RCS380.VENDOR_ID, (short) RCS380.PRODUCT_ID);
LibUsb.setAutoDetachKernelDriver(dh, true);
LibUsb.setConfiguration(dh, 1);

Accédez immédiatement à UsbPipe

De là, vous pouvez accéder à UsbPipe immédiatement dans le style Imozuru.

RCS380.java


            rcs380 = this.findDevice(rootHub, RCS380.VENDOR_ID, RCS380.PRODUCT_ID);
            UsbConfiguration configuration = (UsbConfiguration) rcs380.getUsbConfigurations().get(0);
            this.iface = (UsbInterface) configuration.getUsbInterfaces().get(0);


            UsbEndpoint endpointOut = null, endpointIn = null;
            for (int i = 0; i < iface.getUsbEndpoints().size(); i++) {
                byte endpointAddr = (byte) ((UsbEndpoint) (iface.getUsbEndpoints().get(i))).getUsbEndpointDescriptor().bEndpointAddress();
                if (((endpointAddr & 0x80) == 0x80)) {
                    endpointIn = (UsbEndpoint) (iface.getUsbEndpoints().get(i));
                } else if ((endpointAddr & 0x80) == 0x00) {
                    endpointOut = (UsbEndpoint) (iface.getUsbEndpoints().get(i))
                    ;
                }
            }

            this.pipeOut = endpointOut.getUsbPipe();
            this.pipeIn = endpointIn.getUsbPipe();

Le point ici est qu'il semble y avoir une règle selon laquelle les 4 premiers bits de l'adresse EndPoint dans la direction USB vers l'hôte (IN) sont 0x8. Donc, si vous prenez AND à 0x80 et qu'il reste, c'est pour IN, sinon c'est pour OUT.

Soumettez vos données à UsbPipe et communiquez

Pour les commandes détaillées et la structure de données du RC-S380, je pense qu'il est rapide de se référer à la référence mentionnée au début, donc je vais l'omettre ici. De là à l'appareil

  1. ACK (pas de données de retour)
  2. Set Command Type
  3. Get Firmware version
  4. Get PD DATA version
  5. Switch RF
  6. In Set RF
  7. In Set Protocol

Et continuez à lancer la commande, et enfin lancez la commande en interrogation.


 buf = rcs380.sendCommand(Chipset.CMD_GET_FIRMWARE_VERSION);
            System.out.println("Firmware version: " + String.format("%d.%02d", buf.get(1), buf.get(0)));

            buf = rcs380.sendCommand(Chipset.CMD_GET_PD_DATA_VERSION);
            System.out.println("PD Data version: " + String.format("%d.%02d", buf.get(1), buf.get(0)));

            rcs380.sendCommand(Chipset.CMD_SWITCH_RF, new byte[]{0x00});

            //0x01010f01 : F
            //0x02030f03 : A
            //0x03070f07 : B
            rcs380.sendCommand(Chipset.CMD_IN_SET_RF, new byte[]{0x01, 0x01, 0x0f, 0x01});
            rcs380.sendCommand(Chipset.CMD_IN_SET_PROTOCOL, new byte[]{0x00, 0x18, 0x01, 0x01, 0x02, 0x01, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x08, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0e, 0x04, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x06});
            rcs380.sendCommand(Chipset.CMD_IN_SET_PROTOCOL, new byte[]{0x00, 0x18});

Encore une fois, je pense qu'il est préférable de voir les articles et implémentations des ancêtres pour le code et la structure de données de la commande ...!

Ci-dessous, la partie qui lit Felica.

 System.out.println("********** Start **********");

            boolean isLoop = true;
            while (isLoop) {
                buf = rcs380.sendCommand(Chipset.CMD_IN_COMM_RF, new byte[]{0x6e, 0x00, 0x06, 0x00, (byte) 0xff, (byte) 0xff, 0x01, 0x00});
                if (Arrays.equals(buf.array(), new byte[]{(byte) 0x80, 0x00, 0x00, 0x00})) {

                } else {
                    //Type-F
                    if (buf.get(5) == 0x14 && buf.get(6) == 0x01) {
                        System.out.println("IDm: " + Hex.encodeHexString(Arrays.copyOfRange(buf.array(), 7, 15)));
                        System.out.println("PMm: " + Hex.encodeHexString(Arrays.copyOfRange(buf.array(), 15, 23)));
                        isLoop = false;
                    }
                }

                Thread.sleep(250);
            }

Lorsque vous avez terminé, fermez les tuyaux et ainsi de suite.

rcs380.close();

Voici les résultats de l'exécution.

/Library/Java/JavaVirtualMachi ... ...
SONY RC-S380/P
Firmware version: 1.17
PD Data version: 1.00
********** Start **********
IDm: 01120312eb18f200
PMm: 100b4b428485d0ff

Process finished with exit code 0

Cette source

C'est du code sale à des fins de test, mais il est ci-dessous. https://github.com/nearprosmith/java-rcs380-test

N'hésitez pas à signaler toute erreur ou erreur.

Recommended Posts

Lire Felica en utilisant RC-S380 (PaSoRi) en Java
Lire JSON en Java
Lire des fichiers binaires en Java 1
Lire des fichiers binaires dans Java 2
Lire le fichier de propriétés Java en C #
Chiffrer à l'aide du chiffrement RSA en Java
Lire CSV en Java (annotation Super CSV)
Connexion HTTPS utilisant tls1.2 dans Java 6
J'ai essayé d'utiliser JWT en Java
J'ai essayé d'utiliser l'API Elasticsearch en Java
Essayez d'utiliser l'API Stream en Java
Mapper sans utiliser de tableau en java
ERRORCODE = -4471 se produit dans une application Java qui utilise Db2.
Essayez d'utiliser l'API au format JSON en Java
Lire le fichier xlsx en Java avec Selenium
Lire une chaîne dans un fichier PDF avec Java
ChatWork4j pour l'utilisation de l'API ChatWork en Java
Partition en Java
[Java] Création d'API à l'aide de Jerjey (Jax-rs) avec eclipse
Envoyer des e-mails à l'aide d'Amazon SES SMTP en Java
Envoyer des notifications push à l'aide de Notification Hubs en Java
Changements dans Java 11
Essayez d'utiliser Sourcetrail (version win) avec du code Java
Janken à Java
Essayez d'utiliser Sourcetrail (version macOS) avec du code Java
Faire correspondre les adresses IP à l'aide d'expressions régulières en Java
Ajouter, lire et supprimer des commentaires Excel à l'aide de Java
[Java] Lire les fichiers dans src / main / resources
Afficher "Hello World" dans le navigateur à l'aide de Java
Afficher "Hello World" dans le navigateur à l'aide de Java
Taux circonférentiel à Java
Essayez d'utiliser l'analyse syntaxique de l'API COTOHA en Java
NLP4J [001b] Analyse morphologique en Java (utilisant kuromoji)
FizzBuzz en Java
Convertir JSON et YAML en Java (en utilisant Jackson et SnakeYAML)
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
J'ai essayé d'utiliser l'instruction Extended for en Java
Essayez le hooking global en Java à l'aide de la bibliothèque JNativeHook
Différences de code lors de l'utilisation du système de longueur en Java
Tri à l'aide du comparateur java
Implémentation de l'interpréteur par Java
Application Janken en Java
Programmation par contraintes en Java
Mettez java8 dans centos7
NVL-ish guy en Java
Joindre des tableaux en Java
"Hello World" en Java
Lire le fichier de propriétés Java
Interface appelable en Java
Commentaires dans la source Java
Formater XML en Java
Simple htmlspecialchars en Java
Pratique de grattage avec Java ②
Implémentation Boyer-Moore en Java
Lire la source Java HashMap
Hello World en Java
Utiliser OpenCV avec Java
Mémorandum WebApi avec Java