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

org.bidib.jbidibc.usbhid.UsbManager Maven / Gradle / Ivy

package org.bidib.jbidibc.usbhid;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.ConfigDescriptor;
import org.usb4java.DescriptorUtils;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceHandle;
import org.usb4java.DeviceList;
import org.usb4java.EndpointDescriptor;
import org.usb4java.Interface;
import org.usb4java.InterfaceDescriptor;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;

public class UsbManager implements AutoCloseable {

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

    public static final int USB_VENDOR_ID_CP2112 = 0x10C4; // Silicon Laboratories

    public static final int USB_DEVICE_ID_CP2112 = 0xEA90;

    // tinyusb -->https://github.com/harbaum/I2C-Tiny-USB/tree/master/digispark
    public static final int USB_VENDOR_ID_TINYUSB = 0x0403;

    public static final int USB_DEVICE_ID_TINYUSB = 0xC631;

    private boolean initialized;

    public UsbManager() {

    }

    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);
        }

        this.initialized = true;

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

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

    public Device findDevice(DeviceVidPid... deviceVidPids) {

        Device device = null;
        for (DeviceVidPid devVidPid : deviceVidPids) {
            device = findDevice(devVidPid.getVid(), devVidPid.getPid());
            LOGGER.info("Found supported device: {}", device);

            if (device != null) {
                break;
            }
        }

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

        return device;
    }

    public Device findDevice(int vendorId, int productId) {

        // Read the USB device list
        DeviceList list = new DeviceList();
        int result = LibUsb.getDeviceList(null, list);
        if (result < LibUsb.SUCCESS) {
            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() & 0xFFFF) == vendorId && (descriptor.idProduct() & 0xFFFF) == 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 {
        LOGGER.info("Close the UsbManager instance.");

        LibUsb.exit(null);

        this.initialized = false;
    }

    public Map getDeviceList() {

        if (!initialized) {
            LOGGER.error("Initialize the UsbManager before get the device list.");
            return Collections.emptyMap();
        }

        Map deviceList = new HashMap();

        // 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);

                // prepare the key
                String deviceName = String.format("%04x:%04x", descriptor.idVendor(), descriptor.idProduct());

                final ConfigDescriptor configDescriptor = new ConfigDescriptor();

                // result = LibUsb.getActiveConfigDescriptor(device, configDescriptor);
                result = LibUsb.getConfigDescriptor(device, (byte) 0, configDescriptor);

                if (result != LibUsb.SUCCESS) {

                    // TODO

                    // throw new LibUsbException("Unable to read config descriptor", result);
                    LOGGER.warn("Unable to read config descriptor");
                    continue;
                }

                LOGGER.info("Current configDescriptor: {}", DescriptorUtils.dump(configDescriptor));

                int numConfigurations = descriptor.bNumConfigurations() & 0xFF;
                int deviceAddress = LibUsb.getDeviceAddress(device);
                int attributes = configDescriptor.bmAttributes() & 0xff;
                int maxPower = (configDescriptor.bMaxPower() & 0xff) * 2;

                String mManufacturerName = null;
                String mProductName = null;
                String mSerialNumber = null;

                final DeviceHandle deviceHandle = new DeviceHandle();
                result = LibUsb.open(device, deviceHandle);
                if (result != LibUsb.SUCCESS) {
                    LOGGER.warn("Failed to open the device, result: {}", result);
                }
                else {
                    try {
                        mManufacturerName = LibUsb.getStringDescriptor(deviceHandle, descriptor.iManufacturer());
                        mProductName = LibUsb.getStringDescriptor(deviceHandle, descriptor.iProduct());
                        mSerialNumber = LibUsb.getStringDescriptor(deviceHandle, descriptor.iSerialNumber());
                        LOGGER
                            .info("Fetched mManufacturerName: {}, mProductName: {}, mSerialNumber: {}",
                                mManufacturerName, mProductName, mSerialNumber);
                    }
                    finally {
                        LibUsb.close(deviceHandle);
                    }
                }

                UsbConfiguration[] configurations = new UsbConfiguration[numConfigurations];
                UsbConfiguration config = new UsbConfiguration(deviceAddress, deviceName, attributes, maxPower);
                configurations[0] = config;

                // TODO get the interfaces

                // TODO set the configuration

                List interfaces = new ArrayList<>();
                List endpoints = new ArrayList<>();
                int interfaceId = 0;
                int intClass = 0;
                int subClass = 0;
                int protocol = 0;
                for (final Interface iface : configDescriptor.iface()) {

                    int numAlternateSetting = iface.numAltsetting();

                    for (final InterfaceDescriptor intDesc : iface.altsetting()) {

                        interfaceId = intDesc.bInterfaceNumber() & 0xff;
                        intClass = intDesc.bInterfaceClass() & 0xff;
                        subClass = intDesc.bInterfaceSubClass() & 0xff;
                        protocol = intDesc.bInterfaceProtocol() & 0xff;

                        for (final EndpointDescriptor epDesc : intDesc.endpoint()) {

                            int endpointAddress = epDesc.bEndpointAddress() & 0xFF;
                            LOGGER.info("Current endpoint address: {}", endpointAddress);
                            int epAttributes = epDesc.bmAttributes() & 0xff;
                            int maxPacketSize = epDesc.wMaxPacketSize() & 0xff;
                            int interval = epDesc.bInterval() & 0xff;

                            UsbEndpoint endpoint =
                                new UsbEndpoint(endpointAddress, epAttributes, maxPacketSize, interval);
                            endpoints.add(endpoint);
                        }

                    }
                    UsbInterface ifc =
                        new UsbInterface(interfaceId, numAlternateSetting, null, intClass, subClass, protocol);
                    ifc.setEndpoints(endpoints.toArray(new UsbEndpoint[0]));

                    interfaces.add(ifc);

                }
                config.setInterfaces(interfaces.toArray(new UsbInterface[0]));

                final UsbDevice usbDevice =
                    new UsbDevice(descriptor.idVendor() & 0xFFFF, descriptor.idProduct() & 0xFFFF, deviceName,
                        configurations, mManufacturerName, mProductName, mSerialNumber);

                deviceList.put(deviceName, usbDevice);

                LibUsb.freeConfigDescriptor(configDescriptor);
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Failed to load the device description.", ex);
        }
        finally {
            // Ensure the allocated device list is freed
            LibUsb.freeDeviceList(list, true);
        }

        return deviceList;
    }

    public UsbDeviceConnection openDevice(UsbDevice usbDevice) {
        LOGGER.info("Create connection for usbDevice: {}", usbDevice);

        final UsbDeviceConnection usbDeviceConnection = new UsbDeviceConnection(usbDevice);
        usbDeviceConnection.open();

        return usbDeviceConnection;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy