usb4java:无法使数据传输工作

时间:2016-09-20 22:42:44

标签: java windows usb usb4java

我正在尝试使用usb4java(低级API)与在Windows上设置为HID设备的USB连接科学仪器(x86和x86_64)进行通信。有一个非常古老的C ++应用程序可以正常工作,但我正在尝试用纯Java替换它,原因有多种。

我可以获取设备描述符并确定接口/端点,但异步传输永远不会发生(由Device Monitoring Studio检查),并且永远不会调用回调。 usb4java没有抛出任何异常,也不知道我是否可以访问libusb级别的任何日志(如果可能的话)。我是处理硬件的完全新手,所以它可能是我缺少的基本内容。

只有一个端点,我不确定C ++代码如何管理双向通信。代码中没有明确提及传输类型,因为所有细节都隐藏在第三方库中。

我安装了libusbK驱动程序,我尝试了高级实现(javax-usb)。转移仍然没有通过。

以下是端点描述符转储的输出,以及代码的缩写版本。

    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              100
  extralen                 0
  extra:

以下是代码:

import java.nio.*;
import java.util.*;
import org.usb4java.*;


/**
 * This class is intended to test USB communication using usb4java
 *
 */
public class Test {

    private static final String vendorId = "VVV";
    private static final String productId = "PPP";

    private Context context;
    private Device device;
    private Handle handle;

    static volatile boolean exit = false;
    Object synchObj = new Object();
    boolean readCompleted = false;

    private static final int BUFFER_SIZE = 8;

    private final byte[] idQuery = new byte[]{ 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

    public Test(){

        initialize();

        if (device == null){
            System.out.println("No target devices found");
            System.exit(0);
        }

        boolean loop = true;

        //claim interface 0
        int result = LibUsb.claimInterface(handle, 0);
        if (result != LibUsb.SUCCESS)   throw new LibUsbException("Unable to claim interface", result);

        //this code doesn't get executed because the transfer never completes correctly
        final TransferCallback readCallback = new TransferCallback(){
            public void processTransfer(Transfer transfer){
                System.out.println(transfer.actualLength() + " bytes sent");

                //read the response here

                synchronized (synchObj){
                    readCompleted = true;
                    synchObj.notify();
                }
            }
        };

        //initial request writing the device identification query
        write(handle, idQuery, readCallback);

        //waiting for the write/response to complete
        while (loop){           
            synchronized (synchObj){
                while (!readCompleted){
                    try{
                        synchObj.wait();
                    }
                    catch (InterruptedException ex){
                        ex.printStackTrace();
                    }
                }
            }
            readCompleted = false;
            loop = false;
            System.out.println("Completed reading");
        }

        result = LibUsb.releaseInterface(handle, 0);
        LibUsb.close(handle);

    }

    private void initialize(){
        try{
            context = new Context();
            int result = LibUsb.init(context);
            if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to initialize libusb.", result);    

            DeviceList deviceList = new DeviceList();
            result = LibUsb.getDeviceList(context, deviceList);
            if (result < 0) throw new LibUsbException("Unable to get device list.", result);

            for (int i = 0; i < deviceList.getSize(); i++){
                Device dev = deviceList.get(i);

                DeviceHandle h = new DeviceHandle();
                int res = LibUsb.open(dev, h);
                if (res != LibUsb.SUCCESS) continue;

                DeviceDescriptor descriptor = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(dev, descriptor);
                if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to read device descriptor", result);

                String dump = descriptor.dump(h);               
                if (dump.indexOf("PPP") > -1){
                    device = dev;
                    handle = h;
                    System.out.println("Found target device");
                    break;
                }
            }

        }
        catch (Exception ex){
            ex.printStackTrace();
        }
    }

    public static void write(DeviceHandle handle, byte[] data, TransferCallback callback){
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(data.length);
        buffer.put(data);
        Transfer transfer = LibUsb.allocTransfer();
        LibUsb.fillInterruptTransfer(transfer, handle, (byte)0x81, buffer, callback, null, 1000);
        System.out.println("Sending " + data.length + " bytes to device");
        int result = LibUsb.submitTransfer(transfer);
        if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to submit transfer", result);
    }

    public static void main(String[] args){
        Test app = new Test();
    }
}

提前感谢任何建议。

1 个答案:

答案 0 :(得分:1)

首先:如果你不是在摆弄和插手,我建议你最好只使用已经提供的软件。因为这是一种科学的装置,所以它有可能弄乱你的读数。

现在为什么这不起作用: 有趣的是这件作品bEndpointAddress 0x81 EP 1 IN。它告诉我们的是,有一个端点可以向主机发送数据。是的,您可以写入此端点。这将等到设备有数据要发送,并简单地覆盖您提供的缓冲区中的数据。

至于为什么会这样:你正在处理HID。更好地阅读它,因为你不能简单地获得ASCII缓冲区,但需要根据HID协议解释特殊格式的字节数组。

将数据发送到此设备的唯一方法是使用端点0x00上的控制传输。

最简单的入门方法是使用带有usb嗅探器的c ++软件,并尝试了解来回传输的数据。