2

我正在尝试使用 usb4java(低级 API)与在 Windows(x86 和 x86_64)上设置为 HID 设备的 USB 连接科学仪器进行通信。有一个非常古老的 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();
    }
}

在此先感谢您的任何建议。

4

1 回答 1

1

首先:如果您不喜欢摆弄和插手,我建议您最好使用已经提供的软件。前面有大量工作要做,因为这是一种科学设备,所以有可能会弄乱你的读数。

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

至于为什么会这样:您正在处理 HID。更好地阅读它,因为您不会得到简单的 ASCII 缓冲区,而是必须根据 HID 协议解释的特殊格式的字节数组。

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

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

于 2016-09-21T08:48:56.563 回答