All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.jbidibc.ch341a.libusb.Ch341A Maven / Gradle / Ivy

Go to download

jBiDiB jbidibc USB POM Install the libusb drivers for using the libusb access. Under Windows OS you must install the Zadig driver as described here: https://github.com/libusb/libusb/wiki/Windows. Zadic can be downloaded from: http://zadig.akeo.ie/ In the Zadig UI you must check Options > List all devices and the select the 'USB-EPP /I2C... CH341A' device. Then select the target driver with the spinners (I used libusb-win32 (v1.2.6.0)) and click the 'Install driver' button.

There is a newer version: 2.0.26
Show newest version
package org.bidib.jbidibc.ch341a.libusb;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.BufferUtils;
import org.usb4java.ConfigDescriptor;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceHandle;
import org.usb4java.DeviceList;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;
import org.usb4java.Transfer;
import org.usb4java.TransferCallback;

public class Ch341A implements AutoCloseable {

    private static final Logger LOGGER = LoggerFactory.getLogger(Ch341A.class);

    public static final short USB_VENDOR_ID_CH341 = 0x1a86; // Dev : (1a86) QinHeng Electronics

    public static final short USB_DEVICE_ID_CH341_I2C = 0x5512; // (5512) CH341A in I2C mode

    public static final short USB_DEVICE_ID_CH341_UART = 0x5523; // (5523) CH341A in UART mode

    /** The interface number. */
    private static final byte DEFAULT_INTERFACE = 0;

    private static final int DEFAULT_CONFIGURATION = 0x01;

    private static final byte BULK_WRITE_ENDPOINT = 0x02;

    private static final byte BULK_READ_ENDPOINT = (byte) 0x82;

    private static final int DEFAULT_TIMEOUT = 300; // 300mS for USB timeouts

    private static final int IN_BUF_SZ = 0x100;

    private static final int EEPROM_WRITE_BUF_SZ = 0x2b; // only for 24c64 / 24c32 ??

    private static final int EEPROM_READ_BULKIN_BUF_SZ = 0x20;

    private static final int EEPROM_READ_BULKOUT_BUF_SZ = 0x65;

    private static final byte mCH341A_CMD_I2C_STREAM = (byte) 0xAA;

    private static final byte mCH341A_CMD_I2C_STM_SET = (byte) 0x60;

    private static final byte mCH341A_CMD_I2C_STM_STA = (byte) 0x74;

    private static final byte mCH341A_CMD_I2C_STM_STO = (byte) 0x75;

    private static final byte mCH341A_CMD_I2C_STM_OUT = (byte) 0x80;

    private static final byte mCH341A_CMD_I2C_STM_END = (byte) 0x00;

    /** The communication timeout in milliseconds. */
    private static final int TIMEOUT = 1000;

    // CH341a READ EEPROM setup packet for the 24c64
    // this needs putting into a struct to allow convenient access to individual elements

    // #define CH341_EEPROM_READ_SETUP_CMD "\xaa\x74\x83\xa0\x00\x00\x74\x81\xa1\xe0\x00\x00\x06\x04\x00\x00" \
    // "\x00\x00\x00\x00\x40\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \
    // "\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \
    // "\xd9\x8b\x41\x7e\x00\xf0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \
    // "\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \
    // "\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
    // "\xaa\xdf\xc0\x75\x00"

    // @formatter:off
    private static final byte[] CH341_EEPROM_READ_SETUP_CMD =
        { (byte) 0xAA, 0x74, (byte) 0x83, (byte) 0xa0, 0x00, 0x00, 0x74, (byte) 0x81, (byte) 0xa1, (byte) 0xe0, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 
            0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x11, 0x4d, 0x40, 0x77, (byte) 0xcd, (byte) 0xab, (byte) 0xba, (byte) 0xdc,
            (byte) 0xaa, (byte) 0xe0, 0x00, 0x00, (byte) 0xc4, (byte) 0xf1, 0x12, 0x00, 0x11, 0x4d, 0x40, 0x77, (byte) 0xf0, (byte) 0xf1, 0x12, 0x00,
            (byte) 0xd9, (byte) 0x8b, 0x41, 0x7e, 0x00, (byte) 0xf0, (byte) 0xfd, 0x7f, (byte) 0xf0, (byte) 0xf1, 0x12, 0x00, 0x5a, (byte) 0x88, 0x41, 0x7e,
            (byte) 0xaa, (byte) 0xe0, 0x00, 0x00, 0x2a, (byte) 0x88, 0x41, 0x7e, 0x06, 0x04, 0x00, 0x00, 0x11, 0x4d, 0x40, 0x77,
            (byte) 0xe8, (byte) 0xf3, 0x12, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            (byte) 0xaa, (byte) 0xdf, (byte) 0xc0, 0x75, 0x00};
    // @formatter:on

    //
    //// for 24c64
    // #define CH341_EEPROM_READ_NEXT_CMD "\xaa\x74\x83\xa0\x00\x00\x74\x81\xa1\xe0\x00\x00\x10\x00\x00\x00" \
    // "\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
    // "\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \
    // "\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \
    // "\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\x12\x01\x19\x00" \
    // "\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9c\x2e\x68\x00" \
    // "\xaa\xdf\xc0\x75\x00"
    // @formatter:off
    private static final byte[] CH341_EEPROM_READ_NEXT_CMD =
        { (byte) 0xAA, 0x74, (byte) 0x83, (byte) 0xa0, 0x00, 0x00, 0x74, (byte) 0x81, (byte) 0xa1, (byte) 0xe0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
            0x00, 0x00, 0x00, 0x00, (byte) 0x8c, (byte) 0xf1, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            (byte) 0xaa, (byte) 0xe0, 0x00, 0x00, (byte) 0xc4, (byte) 0xf1, 0x12, 0x00, 0x5d, 0x22, (byte) 0xd7, 0x5a, (byte) 0xdc, (byte) 0xf1, 0x12, 0x00,
            (byte) 0x8f, 0x04, 0x44, 0x7e, 0x30, (byte) 0x88, 0x41, 0x7e, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x2a, (byte) 0x88, 0x41, 0x7e,
            (byte) 0xaa, (byte) 0xe0, (byte) 0x00, (byte) 0x7e, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x69, (byte) 0x0e, (byte) 0x3c, (byte) 0x00, (byte) 0x12, (byte) 0x01, (byte) 0x19, (byte) 0x00, 
            (byte) 0x0f, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x9c, (byte) 0x2e, (byte) 0x68, (byte) 0x00,
            (byte) 0xaa, (byte) 0xdf, (byte) 0xc0, 0x75, 0x00};
    // @formatter:on

    // private Context context;

    private DeviceHandle handle;

    private boolean detachKernelDriver;

    public void setLibUsbDebugLevel(int logLevel) {

        LibUsb.setOption(null, LibUsb.OPTION_LOG_LEVEL, logLevel);

    }

    public void init(Integer logLevel) {
        // context = new Context();
        int result = LibUsb.init(null);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Unable to initialize libusb.", result);
        }

        if (logLevel != null) {
            LibUsb.setOption(null, LibUsb.OPTION_LOG_LEVEL, logLevel);
        }

        // // Read the device descriptor
        // final DeviceDescriptor descriptor = new DeviceDescriptor();
        // result = LibUsb.getDeviceDescriptor(device, descriptor);
        // if (result < 0) {
        // throw new LibUsbException("Unable to read device descriptor", result);
        // }
    }

    // vendor Silicon Laboratories 10C4
    // product CP2112 HID USB-to-SMBus Bridge EA90

    public Device findDevice() {
        Device device = findDevice(USB_VENDOR_ID_CH341, USB_DEVICE_ID_CH341_I2C);
        LOGGER.info("Found device: {}", device);

        if (device == null) {
            throw new RuntimeException("No CH341A device found!");
        }

        return device;
    }

    public DeviceHandle openDevice(/* Device device */) {

        int result = -1;
        // DeviceHandle handle = new DeviceHandle();
        //
        // device = LibUsb.refDevice(device);
        //
        // int result = LibUsb.open(device, handle);
        // if (result != LibUsb.SUCCESS) {
        // throw new LibUsbException("Unable to open USB device", result);
        // }

        // // Open test device
        final DeviceHandle handle = LibUsb.openDeviceWithVidPid(null, USB_VENDOR_ID_CH341, USB_DEVICE_ID_CH341_I2C);
        if (handle == null) {
            throw new RuntimeException("Unable to open USB device");
        }

        LOGGER.info("Open device passed, handle: {}", handle);
        this.handle = handle;

        Device device = LibUsb.getDevice(handle);

        LOGGER.info("Get device passed, device: {}", device);

        LOGGER
            .info("Found [{}:{}] as device [{}] on USB bus [{}]\n", USB_VENDOR_ID_CH341, USB_DEVICE_ID_CH341_I2C,
                LibUsb.getDeviceAddress(device), LibUsb.getBusNumber(device));

        detachKernelDriver = LibUsb.kernelDriverActive(handle, DEFAULT_INTERFACE) > 0;
        if (detachKernelDriver) {
            int ret = LibUsb.detachKernelDriver(handle, DEFAULT_INTERFACE);
            if (ret > 0) {
                LOGGER.warn("Failed to detach kernel driver: {}", ret);
                throw new LibUsbException("Unable to open USB device", ret);
            }
            else {
                LOGGER.info("Detached kernel driver.");
            }
        }
        else {
            LOGGER.info("No kernel driver active.");
        }

        IntBuffer currentConfig = IntBuffer.allocate(1);

        result = LibUsb.getConfiguration(handle, currentConfig);
        if (result != LibUsb.SUCCESS) {
            LOGGER.warn("Failed to get current device configuration: {}", result);
            // return NULL;
        }

        LOGGER.info("Current configuration: {}", currentConfig);

        if (currentConfig.get(0) != DEFAULT_CONFIGURATION) {
            result = LibUsb.setConfiguration(handle, DEFAULT_CONFIGURATION);
        }

        if (result != LibUsb.SUCCESS) {
            LOGGER.warn("Failed to set device configuration to {}: {}", DEFAULT_CONFIGURATION, result);
            // return NULL;
        }

        // Claim the ADB interface
        result = LibUsb.claimInterface(handle, DEFAULT_INTERFACE);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Unable to claim interface", result);
        }

        LOGGER.info("Claim interface passed.");

        ByteBuffer ch341DescriptorBuffer = ByteBuffer.allocateDirect(0x12);
        result = LibUsb.getDescriptor(handle, LibUsb.DT_DEVICE, (byte) 0x00, ch341DescriptorBuffer);
        if (result < LibUsb.SUCCESS) {
            // throw new LibUsbException("Unable to claim interface", result);
            LOGGER.warn("Unable to get the device descriptor, result: {}", result);
        }
        else {
            LOGGER
                .info(String
                    .format("Device reported its revision [%d.%02d]", ch341DescriptorBuffer.get(13),
                        ch341DescriptorBuffer.get(12)));

            byte[] temp = new byte[0x12];
            ch341DescriptorBuffer.get(temp);
            LOGGER.info("Device descriptor: {}", ByteUtils.bytesToHex(temp));
        }

        try {
            // Use device handle here
            ConfigDescriptor descriptor = new ConfigDescriptor();
            result = LibUsb.getActiveConfigDescriptor(device, descriptor);
            if (result != LibUsb.SUCCESS) {
                throw new LibUsbException("Unable to get the config descriptor", result);
            }

            LOGGER.info("Current config descriptor: {}", descriptor);

        }
        finally {

            // LOGGER.info("Release the interface.");
            // result = LibUsb.releaseInterface(handle, DEFAULT_INTERFACE);
            // if (result != LibUsb.SUCCESS) {
            // // throw new LibUsbException("Unable to release interface", result);
            // LOGGER.warn("Unable to release interface: {}", result);
            // }
            //
            // // Attach the kernel driver again if needed
            // if (detach) {
            // result = LibUsb.attachKernelDriver(handle, DEFAULT_INTERFACE);
            // if (result != LibUsb.SUCCESS) {
            // LOGGER.warn("Unable to re-attach kernel driver: {}", result);
            // // throw new LibUsbException("Unable to re-attach kernel driver", result);
            // }
            // }
            //
            // LibUsb.close(handle);
        }

        return handle;
    }

    public void close(DeviceHandle handle) {

        int result = -1;
        LOGGER.info("Release the interface.");
        result = LibUsb.releaseInterface(handle, DEFAULT_INTERFACE);
        if (result != LibUsb.SUCCESS) {
            // throw new LibUsbException("Unable to release interface", result);
            LOGGER.warn("Unable to release interface: {}", result);
        }

        // Attach the kernel driver again if needed
        if (detachKernelDriver) {
            LOGGER.info("Re-attach the kernel driver.");
            result = LibUsb.attachKernelDriver(handle, DEFAULT_INTERFACE);
            if (result != LibUsb.SUCCESS) {
                LOGGER.warn("Unable to re-attach kernel driver: {}", result);
                // throw new LibUsbException("Unable to re-attach kernel driver", result);
            }

            // reset the flag
            detachKernelDriver = false;
        }

        LibUsb.close(handle);

        // reset the handle
        handle = null;
    }

    /**
     * @param handle
     *            the device handle
     * @param speed
     *            set the i2c bus speed (speed: 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz)
     */
    public void setStreamSpeed(final DeviceHandle handle, int speed) {

        LOGGER.info("Set the stream speed: {}", speed);

        IntBuffer transferred = IntBuffer.allocate(1);

        byte[] buffer = new byte[3];
        buffer[0] = mCH341A_CMD_I2C_STREAM;
        buffer[1] = (byte) (mCH341A_CMD_I2C_STM_SET | (speed & 0x3));
        buffer[2] = mCH341A_CMD_I2C_STM_END;

        ByteBuffer data = BufferUtils.allocateByteBuffer(/* EEPROM_READ_BULKOUT_BUF_SZ */buffer.length);
        data.put(buffer);

        int result = LibUsb.bulkTransfer(handle, BULK_WRITE_ENDPOINT, data, transferred, DEFAULT_TIMEOUT);

        if (result < LibUsb.SUCCESS) {
            LOGGER.warn("Set the stream speed failed, result: {}", result);
        }

        LOGGER.info("Set the stream speed passed. Total transferred bytes: {}", transferred.get());
    }

    /**
     * Flag set during the asynchronous transfers to indicate the program is finished.
     */
    private volatile boolean exit = false;

    private volatile int getnextpacket = 0;

    private int syncackpkt;

    private static final class ReadBufferHolder {

        private final byte[] readBuffer;

        private int offset;

        public ReadBufferHolder(byte[] readBuffer) {
            this.readBuffer = readBuffer;
        }

        public void append(byte[] buffer) {
            int len = buffer.length;

            System.arraycopy(buffer, 0, readBuffer, offset, len);

            offset += len;
        }

        public byte[] getReadBuffer() {
            return readBuffer;
        }

        public int getReceivedCount() {
            return offset;
        }
    }

    public byte[] ch341readEEPROM(final DeviceHandle handle, int bytestoread) {

        byte[] ch341outBuffer = new byte[EEPROM_READ_BULKOUT_BUF_SZ];
        byte[] ch341inBuffer = new byte[EEPROM_READ_BULKIN_BUF_SZ /* IN_BUF_SZ */]; // 0x100 bytes

        ByteBuffer bufferIn = BufferUtils.allocateByteBuffer(ch341inBuffer.length)/* .order(ByteOrder.LITTLE_ENDIAN) */;
        ByteBuffer bufferOut = BufferUtils.allocateByteBuffer(ch341outBuffer.length);
        bufferOut.put(CH341_EEPROM_READ_SETUP_CMD);

        LOGGER
            .info("Allocated USB transfer structures, size of CH341_EEPROM_READ_SETUP_CMD: {}",
                CH341_EEPROM_READ_SETUP_CMD.length);

        // prepare the read buffer
        byte[] readBuffer = new byte[bytestoread];
        final ReadBufferHolder holder = new ReadBufferHolder(readBuffer);

        Transfer transferIn = LibUsb.allocTransfer(0);
        Transfer transferOut = LibUsb.allocTransfer(0);

        final TransferCallback callbackIn = new TransferCallback() {
            @Override
            public void processTransfer(Transfer transfer) {

                LOGGER.info("In, transfer status: {}", transfer.status());

                switch (transfer.status()) {
                    case LibUsb.TRANSFER_COMPLETED:

                        getnextpacket = 1;
                        break;
                    default:
                        LOGGER.warn("In, transfer failed: {}", transfer.status());
                        getnextpacket = -1;
                        break;
                }

                LOGGER.info("{} bytes received", transfer.actualLength());

                // prepare the buffer for the received data
                byte[] ch341Received = new byte[transfer.actualLength()];

                transfer.buffer().get(ch341Received);
                LOGGER
                    .info("Data received, len: {}, data: {}", transfer.actualLength(),
                        ByteUtils.bytesToHex(ch341Received));

                transfer.buffer().clear();

                if (transfer.userData() != null) {
                    ReadBufferHolder holder = (ReadBufferHolder) transfer.userData();
                    LOGGER.info("Append the received data to the ReadBufferHolder.");
                    holder.append(ch341Received);
                }
            }
        };

        final TransferCallback callbackOut = new TransferCallback() {
            @Override
            public void processTransfer(Transfer transfer) {
                LOGGER.info("Out, Sync/Ack received, status {}\n", transfer.status());
                LOGGER.info("{} bytes sent.", transfer.actualLength());

                syncackpkt = 1;
            }
        };

        LibUsb.fillBulkTransfer(transferIn, handle, BULK_READ_ENDPOINT, bufferIn, callbackIn, holder, TIMEOUT);
        LibUsb.fillBulkTransfer(transferOut, handle, BULK_WRITE_ENDPOINT, bufferOut, callbackOut, null, TIMEOUT);

        LOGGER.info("Filled USB transfer structures");
        int result = -1;
        result = LibUsb.submitTransfer(transferIn);

        LOGGER.info("Submitted BULK IN start packet, result: {}", result);

        result = LibUsb.submitTransfer(transferOut);

        LOGGER.info("Submitted BULK OUT setup packet, result: {}", result);

        long start = System.currentTimeMillis();

        long timeout = 100;

        int readpktcount = 0;
        int byteoffset = 0;

        // TODO wait for result data
        while (!exit) {
            LOGGER.info("Read [{}] of [{}] bytes", byteoffset, bytestoread);

            IntBuffer completed = BufferUtils.allocateIntBuffer();

            result = LibUsb.handleEventsTimeoutCompleted(null, timeout, completed);
            LOGGER.info("After handle events timeout, result: {}, completed: {}", result, completed.get());

            if (result != LibUsb.SUCCESS || getnextpacket == -1) { // indicates error
                LOGGER.warn("Wait for timeout failed, result: {}", result);
                exit = true;
            }

            if (getnextpacket == 1) {
                getnextpacket = 0;

                readpktcount++; // increment the read packet counter
                // byteoffset += EEPROM_READ_BULKIN_BUF_SZ;

                byteoffset = holder.getReceivedCount();

                if (byteoffset == bytestoread) {
                    break;
                }

                LOGGER.info("Re-submitting transfer request to BULK IN endpoint.");
                result = LibUsb.submitTransfer(transferIn);

                LOGGER.info("Submitted BULK IN start packet, result: {}", result);

                if (syncackpkt > 0) {
                    LOGGER.info("Reset the syncackpkt.");
                    syncackpkt = 0;
                }

                // if 4th packet received, we are at end of 0x80 byte data block,
                // if it is not the last block, then resubmit request for data
                if (readpktcount == 4) {
                    LOGGER
                        .info(
                            "Submitting next transfer request to BULK OUT endpoint, CH341_EEPROM_READ_NEXT_CMD.length: {}",
                            CH341_EEPROM_READ_NEXT_CMD.length);
                    readpktcount = 0;

                    // TODO if the buffer is not allocated new here we get an exception
                    bufferOut = BufferUtils.allocateByteBuffer(ch341outBuffer.length);
                    bufferOut.put(CH341_EEPROM_READ_NEXT_CMD);

                    bufferOut.put(4, (byte) (byteoffset >> 8 & 0xff));// MSB (big-endian) byte address
                    bufferOut.put(5, (byte) (byteoffset & 0xff)); // LSB of 16-bit byte address

                    LibUsb
                        .fillBulkTransfer(transferOut, handle, BULK_WRITE_ENDPOINT, bufferOut, callbackOut, null,
                            TIMEOUT);

                    LibUsb.submitTransfer(transferOut); // update transfer struct (with new EEPROM page offset)
                                                        // and re-submit next transfer request to BULK OUT endpoint
                }
            }

        }

        long end = System.currentTimeMillis();
        LOGGER.info("Read eeprom finished, duration: {}ms", (end - start));

        // finished, free the transfer objects
        LibUsb.freeTransfer(transferIn);
        LibUsb.freeTransfer(transferOut);

        LOGGER.info("Received data: {}", ByteUtils.bytesToHex(readBuffer));

        return readBuffer;
    }

    /**
     * Asynchronously writes some data to the device.
     * 
     * @param handle
     *            The device handle.
     * @param data
     *            The data to send to the device.
     * @param callback
     *            The callback to execute when data has been transfered.
     */
    public void write(DeviceHandle handle, byte[] data, TransferCallback callback) {
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(data.length);
        buffer.put(data);
        Transfer transfer = LibUsb.allocTransfer();
        // LibUsb.fillBulkTransfer(transfer, handle, OUT_ENDPOINT, buffer, callback, null, TIMEOUT);
        LOGGER.info("Sending {} bytes to device", data.length);
        int result = LibUsb.submitTransfer(transfer);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Unable to submit transfer", result);
        }
    }

    /**
     * Asynchronously reads some data from the device.
     * 
     * @param handle
     *            The device handle.
     * @param size
     *            The number of bytes to read from the device.
     * @param callback
     *            The callback to execute when data has been received.
     */
    public void read(DeviceHandle handle, int size, TransferCallback callback) {
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(size).order(ByteOrder.LITTLE_ENDIAN);
        Transfer transfer = LibUsb.allocTransfer();
        // LibUsb.fillBulkTransfer(transfer, handle, IN_ENDPOINT, buffer, callback, null, TIMEOUT);
        System.out.println("Reading " + size + " bytes from device");
        int result = LibUsb.submitTransfer(transfer);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Unable to submit transfer", result);
        }
    }

    public Device findDevice(short vendorId, short productId) {

        // Read the USB device list
        DeviceList list = new DeviceList();
        int result = LibUsb.getDeviceList(null, list);
        if (result < 0) {
            throw new LibUsbException("Unable to get device list", result);
        }
        LOGGER.info("Found devices: {}", list);

        try {
            // Iterate over all devices and scan for the right one
            for (Device device : list) {
                DeviceDescriptor descriptor = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(device, descriptor);
                if (result != LibUsb.SUCCESS) {
                    throw new LibUsbException("Unable to read device descriptor", result);
                }

                LOGGER.info("Current device: {}", descriptor);

                if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) {

                    int speed = LibUsb.getDeviceSpeed(device);
                    LOGGER.info("Current device speed: {}", speed);
                    return device;
                }
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Failed to load the device descriptot.", ex);
        }
        finally {
            // Ensure the allocated device list is freed
            LibUsb.freeDeviceList(list, true);
        }

        // Device not found
        return null;
    }

    @Override
    public void close() throws Exception {
        if (handle != null) {
            close(handle);
        }

        LibUsb.exit(null);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy