私は usb4java ライブラリを使用しており、USB デバイスの通信方法について多くのことを理解するようになりました。
Web アプリケーションで usb4java 低レベル API (LibUsb 1.0) ライブラリを使用して、Raspberry Pi でバーコード スキャナーの入力を読み取ります。Raspberry Pi は、 Raspbianディストリビューションを通じて最新のパッケージに更新されます。
以下のリソースから Java でこのプロセスを実装する方法の例を次に示します。
USB経由でAdafruit Trinketからデータを読み取る
問題:
私は正常に行うことができます:
- すべてのデバイスを一覧表示する
- ベンダー ID と製品 ID に従ってデバイスを選択
- デバイスを開く
- カーネル ドライバーのデタッチ
- デバイスの要求
そして、スキャナーが送信したデバイスデータを読み取る時間になると、常にタイムアウトエラー (-7) が発生します。
Opening device...
Claiming device...
Found Device, Data below
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Failure reading data -7
Releasing device interface...
Closing...
Exiting...
以下の例では、メソッドを 10 回呼び出して応答を取得し、タイムアウトを 5 秒に設定しています。
for(int i=10; i >= 0; --i)
{
writeOutput(read(DeviceHandle, this.bufferSize, this.timeout, this.transfer));
}
メインクラス: プロセスを説明するために、定義された変数がありません
// Create the libusb context
Context context = new Context();
// Initialize the libusb context
int result = LibUsb.init(context);
if ((result != LibUsb.SUCCESS) || (result < 0))
{
writeOutput("Unable to initialize libusb " + result);
}
else
{
// Try to open the device.
DeviceHandle DeviceHandle = new DeviceHandle();
// Get device
Device device = findDevice((short) 0x0c2e, (short) 0x0200);
if (device == null)
{
writeConsole("Unable to find device");
}
else
{
writeConsole("Device found");
}
// Open I/O with the device handle
result = LibUsb.open(device, DeviceHandle);
if (result < 0)
{
writeOutput("Unable to open device");
DeviceHandle = null;
}
else
{
writeOutput("Opening device");
try
{
boolean detach = LibUsb.hasCapability(LibUsb.CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
int detachActive = LibUsb.kernelDriverActive(DeviceHandle, this.interFace);
// Detach the kernel driver
if ((detach) || (detachActive == 1))
{
result = LibUsb.detachKernelDriver(DeviceHandle, this.interFace);
if (result != LibUsb.SUCCESS)
{
writeOutput("Cannot detach kernel from this interface (" + this.interFace + ") error " + result);
}
else
{
writeOutput("Detaching kernel driver (" + this.interFace + ")");
}
}
//set configuration
result = LibUsb.setConfiguration(DeviceHandle, this.configuration);
if (result != LibUsb.SUCCESS)
{
writeOutput("Cannot set device configuration (" + this.configuration + ") error " + result);
}
else
{
writeOutput("Setting device configuration (" + this.configuration + ")");
// Claim the device
result = LibUsb.claimInterface(DeviceHandle, this.interFace);
if (result != LibUsb.SUCCESS)
{
writeOutput("Cannot open device interface (" + this.interFace + ") error " + result);
}
else
{
try
{
writeOutput("Claiming device on interface (" + this.interFace + ")");
switch(this.transfer)
{
case 0:
writeOutput("Set to Interrupt Transfer type");
break;
case 1:
writeOutput("Set to Bulk Transfer type");
break;
}
for (int i=10; i >= 0; --i)
{
writeOutput(read(DeviceHandle, this.bufferSize, this.timeout, this.transfer));
}
}
finally
{
result = LibUsb.releaseInterface(DeviceHandle, this.interFace);
if (result != LibUsb.SUCCESS)
{
writeOutput("Failure releasing device interface (" + this.interFace + ") error " + result);
}
else
{
writeOutput("Releasing device interface (" + this.interFace + ")");
}
if ((detach) || (detachActive == 1))
{
result = LibUsb.attachKernelDriver(DeviceHandle, this.interFace);
if (result != LibUsb.SUCCESS)
{
writeOutput("Cannot attach kernel driver back to the device (" + this.interFace + ") error " + result);
}
else
{
writeOutput("Re attaching kernel driver back (" + this.interFace + ")");
}
}
}
}
}
}
finally
{
LibUsb.close(DeviceHandle);
writeOutput("Closing... ");
}
}
LibUsb.exit(context);
writeOutput("Exiting... ");
}
**同期読み取りを取得する私の方法**
// Read data from device after claiming it
public static String read(DeviceHandle handle, int size, long timeout, int readType) {
byte endpointId = (byte) 0x81;
StringBuilder stringBuilder = new StringBuilder();
boolean started = false;
while(true)
{
ByteBuffer buffer = BufferUtils.allocateByteBuffer(size).order(ByteOrder.LITTLE_ENDIAN);
IntBuffer transferred = BufferUtils.allocateIntBuffer();
int result;
switch(readType)
{
case 0:
result = LibUsb.interruptTransfer(handle, endpointId, buffer, transferred, timeout);
break;
case 1:
result = LibUsb.bulkTransfer(handle, endpointId, buffer, transferred, timeout);
break;
default:
result = LibUsb.interruptTransfer(handle, endpointId, buffer, transferred, timeout);
break;
}
if (result != LibUsb.SUCCESS)
{
return "Failure reading data with"
+ " buffer size:"
+ size + " bytes timeout:"
+ timeout + " ms error code:"
+ result;
}
else
{
CharBuffer charBuffer = buffer.asCharBuffer();
while(charBuffer.hasRemaining())
{
char nextChar = charBuffer.get();
if (nextChar == '\n')
started = true; //Start Character
else if(nextChar == '\r' && started)
return stringBuilder.toString(); //End Character
else if(started)
stringBuilder.append(nextChar);
}
}
}
}
これは、USB デバイスの記述子です。
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 Per Interface
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0c2e
idProduct 0x0200
bcdDevice 53.32
iManufacturer 1 Metrologic
iProduct 2 Metrologic Scanner
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 3
bmAttributes 0x80
(Bus Powered)
bMaxPower 300mA
extralen 0
extra:
Interface:
numAltsetting 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 HID
bInterfaceSubClass 1
bInterfaceProtocol 1
iInterface 0
extralen 9
extra:
09 21 11 01 00 01 22 3f 00
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 8
bInterval 10
extralen 0
extra:
--- Device END ---
インターフェイスを 0、IN エンドポイントを 0x81、ベンダー ID を 0x0c2e、製品 ID を 0x0200 として使用しています。また、デバイスは割り込み転送のみを受け入れるため、 LibUsb.bulkTransfer()をLibUsb.interruptTransfer( ) に変更しました。wMaxPacketSizeが示すように、バッファーは 8 バイトに設定されます 。
以下のテストを試してみました。
- バッファ転送サイズを 1 ~ 64 バイトに変更します
- LibUsb.bulkTransfer() を使用
- タイムアウトを 100 ~ 20000 ミリ秒に変更しました
- LibUsb.clearhalt(); を追加しました。
この問題を解決するにはどうすればよいですか? 私は何か見落としてますか?