Teensy Arduino 作为 Android HID 设备,在几次输入后停止
Teensy Arduino as Android HID Device, stalls after a few inputs
我的项目是从我的汽车方向盘控件读取按钮输入并将它们(使用类似 Teensy 3.2 Arduino 的)转换为我选择的 android 系统操作(例如提高音量、下一首曲目、确定Google)。
我尝试了 Teensy 提供的几种不同模式来解决这个问题,最初是键盘模拟,然后是操纵杆模拟,现在最后是原始 HID 设备。所有这些模式在 Windows 和 Linux 上都能完美运行,但在 android 上不起作用(我已经在目标设备 运行ning Android 4.1 和Android 5 设备,均无效。
我最接近这个工作的是作为一个 RawHID 设备,我编写了一个小应用程序来解码数据包并转换为系统操作。 这确实有效...大约需要按 2-5 次按钮。然后什么都没有。为了让我的下一个 2-5 按钮按下,我必须拔下设备并重新启动程序。该程序在 thisConnection.requestWait() forever. In an older version i used bulkTransfer 处停止,它具有类似的效果,在按下 2-5 次按钮后永久返回 -1 并且没有数据。
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;
}
设备循环代码(运行 在单独的低优先级线程上)
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();
}
}
所以我的问题更简洁:
有没有人设法让 Teensy Arduino 通过 USB 以任何方式与 Android 接口?我的 HID 方法有什么问题导致这个 "stalling" 问题吗?
最后,我使用 "Consumer Device" 方法切换到 Arduino Pro Micro which has native USB support, and used the Project-HID library。这与我尝试过的任何 OS/Hardware 组合完美搭配。
我的项目是从我的汽车方向盘控件读取按钮输入并将它们(使用类似 Teensy 3.2 Arduino 的)转换为我选择的 android 系统操作(例如提高音量、下一首曲目、确定Google)。
我尝试了 Teensy 提供的几种不同模式来解决这个问题,最初是键盘模拟,然后是操纵杆模拟,现在最后是原始 HID 设备。所有这些模式在 Windows 和 Linux 上都能完美运行,但在 android 上不起作用(我已经在目标设备 运行ning Android 4.1 和Android 5 设备,均无效。
我最接近这个工作的是作为一个 RawHID 设备,我编写了一个小应用程序来解码数据包并转换为系统操作。 这确实有效...大约需要按 2-5 次按钮。然后什么都没有。为了让我的下一个 2-5 按钮按下,我必须拔下设备并重新启动程序。该程序在 thisConnection.requestWait() forever. In an older version i used bulkTransfer 处停止,它具有类似的效果,在按下 2-5 次按钮后永久返回 -1 并且没有数据。
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;
}
设备循环代码(运行 在单独的低优先级线程上)
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();
}
}
所以我的问题更简洁:
有没有人设法让 Teensy Arduino 通过 USB 以任何方式与 Android 接口?我的 HID 方法有什么问题导致这个 "stalling" 问题吗?
最后,我使用 "Consumer Device" 方法切换到 Arduino Pro Micro which has native USB support, and used the Project-HID library。这与我尝试过的任何 OS/Hardware 组合完美搭配。