usb4java: не удается заставить передачу данных работать

Я пытаюсь использовать usb4java (низкоуровневый API) для связи с научным прибором, подключенным через USB, настроенным как HID-устройство в Windows (как x86, так и x86_64). Для него есть очень старое приложение на C++, которое отлично работает, но я пытаюсь заменить его чистой Java по разным причинам.

Я могу получить дескрипторы устройства и определить интерфейс/конечную точку, но асинхронные передачи никогда не происходят (проверено студией мониторинга устройств), и обратные вызовы никогда не вызываются. 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();
    }
}

Спасибо заранее за любые предложения.


person Sasha    schedule 20.09.2016    source источник


Ответы (1)


Прежде всего: если вы не любите возиться и вмешиваться, я предлагаю вам просто жить с уже предоставленным программным обеспечением. Впереди гора работы, и, поскольку это научное устройство, оно может испортить ваши показания.

Теперь о том, почему это не может работать: интересно, что это кусок bEndpointAddress 0x81 EP 1 IN. Это говорит нам о том, что существует конечная точка, которая может отправлять данные на хост. Да, вы не можете не писать в эту конечную точку. Это будет ждать, пока устройство не получит данные для отправки, и просто перезапишет ваши данные в предоставленном вами буфере.

Что касается того, почему это так: вы имеете дело с HID. Лучше почитайте об этом, потому что вы получите не просто буферы ASCII, а специально отформатированные массивы байтов, которые должны интерпретироваться в соответствии с протоколом HID.

Единственный способ отправить данные на это устройство — использовать передачу управления на конечной точке 0x00.

Самый простой способ начать работу — это использовать программное обеспечение C ++ с USB-сниффером и попытаться разобраться в данных, идущих туда и обратно.

person dryman    schedule 21.09.2016