2016-09-20 18 views
1

我正嘗試使用usb4java(低級別API)與設置爲W​​indows(x86和x86_64)上的HID設備的USB連接的科學儀器進行通信。有一個非常古老的C++應用程序可以正常工作,但我試圖用各種原因將其替換爲純Java。usb4java:無法讓數據傳輸正常工作

我可以獲取設備描述符並確定接口/端點,但從不會發生異步傳輸(由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(); 
    } 
} 

在此先感謝您的任何建議。

回答

0

第一:如果你不是在擺弄和插手,我建議你最好只使用已經提供的軟件。 Theres前面的一大堆工作,因爲這是一個科學的設備,這有可能會弄亂你的閱讀。

現在爲什麼這不起作用: 有趣的是這件作品bEndpointAddress 0x81 EP 1 IN。它告訴我們的是,有一個端點可以將數據發送到主機。是的,您可以而不是寫入此端點。這將一直等到設備有數據發送,並簡單地覆蓋您提供的緩衝區中的數據。

至於爲什麼會出現這種情況:您正在處理HID。更好地閱讀它,因爲您不會簡單地獲取ASCII緩衝區,而是需要根據HID協議進行解釋的特殊格式的字節數組。

將數據發送到此設備的唯一方法是在端點0x00上使用控制傳輸。

最簡單的入門方法是使用帶有USB嗅探器的C++軟件,並試圖理解數據的來回。