4

我正在尝试与使用 HID 接口编程的嵌入式系统进行通信。我收到此错误:

线程“主”org.usb4java.LibUsbException 中的异常:USB 错误 0:无法检查内核驱动程序是否处于活动状态:com.fabioang.usbcustomhid.USB_CustomHID.main(USB_CustomHID.java:157)成功

使用以下代码

import java.util.*;
import java.nio.ByteBuffer;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceHandle;
import org.usb4java.DeviceList;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;

/**
 * @author Fabio
 *
 */
public class USB_CustomHID
{
    /** The vendor ID of the custom HID. */
    private static final short VENDOR_ID = 0x0483;

    /** The product ID of the custom HID. */
    private static final short PRODUCT_ID = 0x5750;

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

    /**
     * Searches for the custom HID and returns it. If there are
     * multiple ones attached then this simple demo only returns
     * the first one.
     * 
     * @return The custom HID USB device or null if not found.
     */
    public static Device findCustomHID()
    {
        // Read the USB device list
        DeviceList list = new DeviceList();
        int result = LibUsb.getDeviceList(null, list);
        if (result < 0)
        {
            throw new RuntimeException(
                "Unable to get device list. Result=" + result);
        }

        try
        {
            // Iterate over all devices and scan for the custom HID
            for (Device device: list)
            {
                DeviceDescriptor descriptor = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(device, descriptor);
                if (result < 0)
                {
                    throw new RuntimeException(
                        "Unable to read device descriptor. Result=" + result);
                }
                if (descriptor.idVendor() == VENDOR_ID
                    && descriptor.idProduct() == PRODUCT_ID) return device;
            }
        }
        finally
        {
            // Ensure the allocated device list is freed
            LibUsb.freeDeviceList(list, false); 
        }

        // No custom HID found
        return null;
    }

    /**
     * Sends a message to the custom HID.
     * 
     * @param handle
     *            The USB device handle.
     * @param message
     *            The message to send.
     */
    public static void sendMessage(DeviceHandle handle, byte[] message)
    {
        ByteBuffer buffer = ByteBuffer.allocateDirect(message.length);
        buffer.put(message);
        buffer.rewind();
        int transfered = LibUsb.controlTransfer(handle,
            (byte) (LibUsb.REQUEST_TYPE_CLASS | LibUsb.RECIPIENT_INTERFACE),
            (byte) 0x09, (short) 2, (short) 1, buffer, TIMEOUT);
        if (transfered < 0)
            throw new LibUsbException("Control transfer failed", transfered);
        if (transfered != message.length)
            throw new RuntimeException("Not all data was sent to device");
    }

    /**
     * Sends a command to the missile launcher.
     * 
     * @param handle
     *            The USB device handle.
     * @param command
     *            The command to send.
     */
    public static void ledControl(DeviceHandle handle, int ledNumber, int ledValue)
    {
        byte[] message = new byte[64];
        message[1] = (byte) (ledNumber);
        message[2] = (byte) (ledValue);
        sendMessage(handle, message);
    }


    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.out.println("USB custom HID controller starting...");

        // Initialize the libusb context
        int result = LibUsb.init(null);
        if (result != LibUsb.SUCCESS)
        {
            throw new LibUsbException("Unable to initialize libusb", result);
        }

        System.out.println("libusb initialized");

        // Search for the custom HID USB device and stop when not found
        Device device = findCustomHID();
        if (device == null)
        {
            System.err.println("Custom HID not found.");
            System.exit(1);
        }

        System.out.println("Device found");

        // Open the device
        DeviceHandle handle = new DeviceHandle();
        result = LibUsb.open(device, handle);
        if (result != LibUsb.SUCCESS)
        {
            throw new LibUsbException("Unable to open USB device", result);
        }
        try
        {
            System.out.println("Opening device");

            // Check if kernel driver is attached to the interface
            int attached = LibUsb.kernelDriverActive(handle, 1);
            if (attached < 0)
            {
                throw new LibUsbException(
                    "Unable to check kernel driver active", result);
            }

            // Detach kernel driver from interface 0 and 1. This can fail if
            // kernel is not attached to the device or operating system
            // doesn't support this operation. These cases are ignored here.
            result = LibUsb.detachKernelDriver(handle, 1);
            if (result != LibUsb.SUCCESS &&
                result != LibUsb.ERROR_NOT_SUPPORTED &&
                result != LibUsb.ERROR_NOT_FOUND)
            {
                throw new LibUsbException("Unable to detach kernel driver",
                    result);
            }

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

            // Read commands and execute them
            System.out.println("System ready");
            ledControl(handle, 1, 1);

            // Release the interface
            result = LibUsb.releaseInterface(handle, 1);
            if (result != LibUsb.SUCCESS)
            {
                throw new LibUsbException("Unable to release interface", 
                    result);
            }

            // Re-attach kernel driver if needed
            if (attached == 1)
            {
                LibUsb.attachKernelDriver(handle, 1);
                if (result != LibUsb.SUCCESS)
                {
                    throw new LibUsbException(
                        "Unable to re-attach kernel driver", result);
                }
            }

            System.out.println("Exiting");
        }
        finally
        {
            LibUsb.close(handle);
        }

        // Deinitialize the libusb context
        LibUsb.exit(null);
    }
}
4

1 回答 1

1

假设您已经制定了Linuxudev规则……(此处提供其他解决方案)。

根据 usb4java低级 API 文档

不正确:

// Check if kernel driver must be detached
boolean detach = LibUsb.hasCapability(LibUsb.CAP_SUPPORTS_DETACH_KERNEL_DRIVER) 
   && LibUsb.kernelDriverActive(handle, interfaceNumber);

不幸的是,他们网站上的这个代码示例不正确,kernelDriverActive不返回 a boolean,而是返回int. API 显示这one一个正匹配(其余是负匹配或错误。)

更正: kernelDriverActive(...) == 1

// Check if kernel driver must be detached
boolean detach = LibUsb.hasCapability(LibUsb.CAP_SUPPORTS_DETACH_KERNEL_DRIVER) 
   && LibUsb.kernelDriverActive(handle, interfaceNumber) == 1;

附带说明一下,我个人建议尽可能使用高级 API,因为它消除了低级猜测。

iface.claim(new UsbInterfacePolicy()
{            
    @Override
    // Force unloading of Kernel driver
    public boolean forceClaim(UsbInterface usbInterface)
    {
        return true;
    }
});

最后一点,对于那些来到这里寻求解决 OS X 内核驱动程序问题的人,请查看这篇文章

在旁注中,我发现此信息(处理冲突、跨平台警告)分散且难以找到,部分原因是常见问题解答部分(sourceforge 与 github、c API 与 Java API、Mac问题与标题非常相似的 Linux 问题、冗长的邮件列表对话的交叉链接)。

或许各个上游项目维护者可以在爬取堆栈溢出的常见问题解答、交叉链接到其他上游常见问题解答以及标记过时的 wiki 文章方面一起工作。

于 2016-02-28T18:15:16.627 回答