I want to use PaSoRi other than Windows! When I think about it, I think Python's nfcpy is the first choice, but I want to do it in Java instead of Python! At that time, I couldn't find the sample code (or almost all Python samples ... !!), so I'd like to summarize up to the point where it works.
As a reference first, I have greatly referred to the following articles. We thank our ancestors for implementing the specifications, etc., as they cannot be obtained without purchasing them as a corporation.
The following projects seem to be new and prosperous, so I will adopt them without thinking about anything. http://usb4java.org/
Looking at the site, it seems that there are Low level API (libusb) and High Level API (javax.usb), and this time it will be easier to understand, so I tried using javax.usb. In this case, the following page will be very helpful. --Accessing USB devices from Java applications
The normal procedure for accessing a USB device using the JSR-80 API is as follows:
Based on the above article, a brief summary of the procedure for communication
As mentioned above, if you know the control command to the device, it is not a difficult procedure.
Since USB can be connected in a tree format with a hub, it is necessary to search for USB in a Imozuru style and find the desired USB. You can get the virtual route below.
RCS380.java
UsbServices services = UsbHostManager.getUsbServices();
UsbHub rootHub = services.getRootUsbHub();
Then look for the device by the vendor and product ID you looked up earlier. This is the sample. Search recursively even if there is a hub in the middle.
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;
}
Device detection is easy!
I wanted to say ..., but there is a point I was addicted to personally here, and if I proceed as it is, the Configuration is not Active, so I fell into a situation where UsbPipe for exchanging at Endpoint 2 could not be opened. It was. I checked if there is a method to setConfiguration or activateConfiguration with javax, but I could not find it, so for later, I will set Configuration using Low Level API (libusb) only in one place here.
//javax.usb.*If it is just, Configuration is not Active, so activate Configuration with LibUSB ...
DeviceHandle dh = LibUsb.openDeviceWithVidPid(null, (short) RCS380.VENDOR_ID, (short) RCS380.PRODUCT_ID);
LibUsb.setAutoDetachKernelDriver(dh, true);
LibUsb.setConfiguration(dh, 1);
From here, you can get up to UsbPipe at once in the Imozuru style.
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();
The point here is that there seems to be a rule that the first 4 bits of the EndPoint address in the direction from USB to the host (IN) is 0x8. So, if you take AND at 0x80 and it remains, it is for IN, otherwise it is for OUT.
For the detailed commands and data structure of RC-S380, I think it is quick to refer to the reference mentioned at the beginning, so I will omit it here. From here to the device
And keep throwing the command, and finally throw the command to polling.
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});
Again, I think it's best to see the articles and implementations of the ancestors for the command code and data structure ...!
Below is the part that is reading 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);
}
When you're done, close the pipes and so on.
rcs380.close();
Below are the execution results.
/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
It's dirty code for testing purposes, but it's below. https://github.com/nearprosmith/java-rcs380-test
Please do not hesitate to point out any typographical errors or mistakes.
Recommended Posts