简体   繁体   English

Teensy Arduino作为Android HID设备,经过几次输入后停顿

[英]Teensy Arduino as Android HID Device, stalls after a few inputs

My project is to read button inputs from my car's steering wheel controls and convert them (using a Teensy 3.2 Arduino-alike) into android system actions of my choosing (eg Volume Up, Next Track, OK Google). 我的项目是从汽车的方向盘控件中读取按钮输入,并将它们(使用Teensy 3.2 Arduino-like)转换为我选择的android系统操作(例如,调高音量,下一曲,确定Google)。

I have tried several different modes that the Teensy provides in order to solve this, initially as a keyboard emulation, followed by Joystick emulation and now finally a Raw HID device. 为了解决这个问题,我尝试了Teensy提供的几种不同模式,最初是键盘模拟,然后是操纵杆模拟,最后是Raw HID设备。 All of these modes work flawlessly on Windows and Linux but do not work on android (I've tried on the target device running Android 4.1 and an Android 5 device, neither work). 所有这些模式都可以在Windows和Linux上正常运行,但不能在android上运行(我已经在运行Android 4.1和Android 5的目标设备上进行了尝试,但都无法正常工作)。

The closest I've managed to get this working is as a RawHID Device with a small app i wrote to decode the packets and convert to system actions. 我设法使它最接近工作的是作为RawHID设备,我编写了一个小应用程序来解码数据包并转换为系统操作。 This actually works ...for about 2-5 button presses. 这实际上可以工作 ...大约需要2-5次按键。 Then nothing. 那什么都没有 In order to get my next 2-5 button presses i have to unplug the device and restart the program. 为了得到我的下一个2-5按钮,我必须拔下设备的电源并重新启动程序。 The program halts on thisConnection. 程序在此连接暂停。 requestWait () forever. requestWait ()永远。 In an older version i used bulkTransfer and it has a similar effect, returning -1 and no data perpetually after 2-5 button presses. 在较旧的版本中,我使用了bulkTransfer ,它具有类似的效果,在按2-5次按钮后,将永久返回-1,并且没有数据。

Code for OpenConnection: OpenConnection的代码:

    public boolean OpenConnection(UsbManager pUsbManager)
    {

        if(ActiveDevice == null) return false;
        if(!hasPermission) return false;
        if(ActiveConnection != null && ActiveEndpoint != null) return true;

        if(hasAssociatedUsbDevice()) {

            ActiveInterface = ActiveDevice.getInterface(InterfaceIndex);
            ActiveEndpoint = ActiveInterface.getEndpoint(EndpointIndex);
            ActiveConnection = pUsbManager.openDevice(ActiveDevice);
            ActiveConnection.claimInterface(ActiveInterface, true);
            ActiveRequest = new UsbRequest();
            ActiveRequest.initialize(ActiveConnection,ActiveEndpoint);

            return true;
        }

        return false;
    }

Code for the device loop (run on a separate low priority thread) 设备循环的代码(在单独的低优先级线程上运行)

private void deviceLoop(Config.HIDDevice pHIDDevice)
{

    try
    {
        if (!pHIDDevice.OpenConnection(mUsbManager)) return;


        ByteBuffer dataBufferIn = ByteBuffer.allocate(64);

        //String activeAppName = mAppDetector.getForegroundAppName(); //TODO: Refactor, causing excessive memory alloc


        String activeAppName = null;

        Config.AppProfile activeProfile = pHIDDevice.getAppProfile(activeAppName);

        while (!mExitDeviceThreads)
        {
            UsbDeviceConnection thisConnection = pHIDDevice.getActiveConnection();
            if (thisConnection == null) break; //connection dropped

            UsbRequest thisRequest = pHIDDevice.getActiveRequest();
            if (thisRequest == null) break; //connection dropped 

            thisRequest.queue(dataBufferIn, dataBufferIn.capacity());

            if (thisConnection.requestWait() == thisRequest)
            {
                byte[] dataIn = dataBufferIn.array();

                for (Config.ButtonPacketMapping thisButtonMapping : pHIDDevice.getButtonPacketMappings())
                {
                    if (thisButtonMapping.Update(dataIn))
                    {
                        for (Config.ButtonAction thisButtonAction : activeProfile.getButtonActions(thisButtonMapping.getName()))
                        {
                            if (thisButtonMapping.getLastValue() == false && thisButtonMapping.getValue() == true)
                            {
                                if (thisButtonAction.buttonAction == Config.ButtonAction.eButtonActionType.Press)
                                {
                                    thisButtonAction.Set();
                                }
                            }
                            else if (thisButtonMapping.getLastValue() == true && thisButtonMapping.getValue() == false)
                            {
                                if (thisButtonAction.buttonAction == Config.ButtonAction.eButtonActionType.Release)
                                {
                                    thisButtonAction.Set();
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                break; //Connection dropped or something went very wrong
            }
        }
    }
    finally
    {
        pHIDDevice.CloseConnection();
    }
}

So my question more succinctly is: 所以我的问题更简洁地是:

Has anyone managed to get a Teensy Arduino to interface with Android in any way at all over USB? 有没有人设法通过USB以任何方式使Teensy Arduino与Android接口? Is there anything wrong with my HID approach to cause this "stalling" problem? 我的HID方法有什么问题导致这种“过时”问题吗?

In the end, I switched to an Arduino Pro Micro which has native USB support, and used the Project-HID library using the "Consumer Device" method. 最后,我切换到了具有本地USB支持的Arduino Pro Micro ,并通过“消费设备”方法使用了Project-HID库 This works perfectly with any OS/Hardware combo that I've tried. 这与我尝试过的任何OS /硬件组合都非常适用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM