如何从未知的USB OTG设备捕获信号?

huangapple go评论77阅读模式
英文:

How to catch signals from a unknown USB OTG device?

问题

我有一个USB OTG设备,它像鼠标一样工作,是在中国购买的,关于所使用的控制器几乎没有更多信息。当我将它连接到我的Android设备时,会出现鼠标光标,并且该设备有5个硬件按钮(左、右、上、下、输入)。我想要为我的应用程序编程这些按钮,以执行特定的任务。因此,我需要读取输入信号并覆盖它们。

我该如何捕获这些信号?

我找到了供应商(0x04D9)和产品ID(0x2519),以及控制器名称* Lenovo Calliope USB Keyboard*。但对于所使用的芯片一无所知,它是隐藏的。

它不适用于onKeyDowndispatchKeyEvent方法。使用USB串口库也不行,因为该设备未找到/识别,提供的VID和PID(请参见与Fatih Şennik的讨论,其他设备可以识别它)。

我目前的假设是这是一个硬件/芯片问题,我无法获取信号。但奇怪的是,该设备在其他方面执行了它应该执行的功能。

英文:

I have a USB OTG device which acts like a mouse, bought in china with not much more information about the used controller. When I connect it to my android there is a mouse cursor and the device has 5 hard buttons (left, right, up, down, enter). I want to programm the buttons for my app to performe specific tasks. So I need to read the input signals and overwrite them.

How can I catch the signals?

I found out the vendor (0x04D9) and product id (0x2519) and the controller name Lenovo Calliope USB Keyboard. But no idea about the used chip, it's covert.

It doesn't work with the methods onKeyDown or dispatchKeyEvent. Also not with USB serial Lib because the device is not found/ recognized with the provided VID und PID (see discussion with Fatih Şennik below, other devices are recognized with it).

My current assumption is that it is a Hardware/ Chip issue that I cannot get the signals. But the strange thing is that the device otherwise does what it is supposed to do.

答案1

得分: 3

你可以使用 USB 串行库,例如 https://github.com/mik3y/usb-serial-for-android,并提供你的 USB OTG 设备的厂商和产品 ID 来控制它。这样,你可以在任何监视器中捕获左、右、上、下和十六进制代码,并根据原始字节进行类似开关的操作。

UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
    // 定义一个回调,当数据被读取时触发
    @Override
    public void onReceivedData(byte[] arg0) {
        String data = null;
        try {
            data = new String(arg0, "UTF-8");
            data.concat("\n");
            switch() // 等等
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
};

首先,让我们尝试连接我们的 Android 手机到 USB OTG 设备。关于产品和厂商 ID,你可以在将其连接到计算机时找到它。如果连接建立成功,剩下的部分就会进行。如果你能在这里分享 USB OTG 设备的数据表,那会很有帮助。

public class MainActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        ProbeTable customTable = new ProbeTable();
        customTable.addProduct(0x0403, 0x6001, CdcAcmSerialDriver.class);

        List<UsbSerialDriver> availableDrivers = new UsbSerialProber(customTable).findAllDrivers(manager);
        ArrayAdapter<String> deviceList = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_2);
        ListView listDevices = (ListView) findViewById(R.id.listView);
        if (!availableDrivers.isEmpty()) {
            for (UsbSerialDriver driver : availableDrivers) {
                deviceList.add(driver.getDevice().getDeviceName());
            }
            listDevices.setAdapter(deviceList);
        } else {
            Toast.makeText(getApplicationContext(), "No devices found", Toast.LENGTH_LONG).show();
        }
    }
}

如果它是 USB HID 设备,尝试下面的代码可能会有帮助:

UsbManager mManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = mManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while (deviceIterator.hasNext()) {
    UsbDevice device = deviceIterator.next();
    Log.i(TAG, "Model: " + device.getDeviceName());
    Log.i(TAG, "ID: " + device.getDeviceId());
    Log.i(TAG, "Class: " + device.getDeviceClass());
    Log.i(TAG, "Protocol: " + device.getDeviceProtocol());
    Log.i(TAG, "Vendor ID " + device.getVendorId());
    Log.i(TAG, "Product ID: " + device.getProductId());
    Log.i(TAG, "Interface count: " + device.getInterfaceCount());
    Log.i(TAG, "---------------------------------------");
    // 获取接口详情
    for (int index = 0; index < device.getInterfaceCount(); index++) {
        UsbInterface mUsbInterface = device.getInterface(index);
        Log.i(TAG, "  *****     *****");
        Log.i(TAG, "  Interface index: " + index);
        Log.i(TAG, "  Interface ID: " + mUsbInterface.getId());
        Log.i(TAG, "  Inteface class: " + mUsbInterface.getInterfaceClass());
        Log.i(TAG, "  Interface protocol: " + mUsbInterface.getInterfaceProtocol());
        Log.i(TAG, "  Endpoint count: " + mUsbInterface.getEndpointCount());
        // 获取端点详情
        for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++) {
            UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
            Log.i(TAG, "    ++++   ++++   ++++");
            Log.i(TAG, "    Endpoint index: " + epi);
            Log.i(TAG, "    Attributes: " + mEndpoint.getAttributes());
            Log.i(TAG, "    Direction: " + mEndpoint.getDirection());
            Log.i(TAG, "    Number: " + mEndpoint.getEndpointNumber());
            Log.i(TAG, "    Interval: " + mEndpoint.getInterval());
            Log.i(TAG, "    Packet size: " + mEndpoint.getMaxPacketSize());
            Log.i(TAG, "    Type: " + mEndpoint.getType());
        }
    }
}
Log.i(TAG, " No more devices connected.");
英文:

You can use a USB serial Lib such as https://github.com/mik3y/usb-serial-for-android and give vendor and product ID of your USB OTG device to control it. So you can catch left, right, up, down and hex codes in any monitor and based on the raw byte, you can do a switch like operation.

UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { 
//Defining a Callback which triggers whenever data is read.
@Override
public void onReceivedData(byte[] arg0) {
String data = null;
try {
data = new String(arg0, &quot;UTF-8&quot;);
data.concat(&quot;/n&quot;);
switch() // etc
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
};

Lets first try this to connect our android phone to the USB otg device. As for the product and vendor ids, you can find it when you plug it to your pc. if the connection is established then the rest will come. it would be helpful if you can share the USB Otg device data sheets here.

public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x0403, 0x6001, CdcAcmSerialDriver.class);
List&lt;UsbSerialDriver&gt; availableDrivers = new UsbSerialProber(customTable).findAllDrivers(manager);
ArrayAdapter&lt;String&gt; deviceList = new ArrayAdapter&lt;String&gt;(MainActivity.this, android.R.layout.simple_list_item_2);
ListView listDevices = (ListView) findViewById(R.id.listView);
if(!availableDrivers.isEmpty()) {
for(UsbSerialDriver driver: availableDrivers) {
deviceList.add(driver.getDevice().getDeviceName());
}
listDevices.setAdapter(deviceList);
} else {
Toast.makeText(getApplicationContext(), &quot;No devices found&quot;, Toast.LENGTH_LONG).show();
}
}
}

if it is USB hid device, Trying this code might help;

UsbManager mManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap&lt;String, UsbDevice&gt; deviceList = mManager.getDeviceList();
Iterator&lt;UsbDevice&gt; deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext())
{
UsbDevice device = deviceIterator.next();
Log.i(TAG,&quot;Model: &quot; + device.getDeviceName());
Log.i(TAG,&quot;ID: &quot; + device.getDeviceId());
Log.i(TAG,&quot;Class: &quot; + device.getDeviceClass());
Log.i(TAG,&quot;Protocol: &quot; + device.getDeviceProtocol());
Log.i(TAG,&quot;Vendor ID &quot; + device.getVendorId());
Log.i(TAG,&quot;Product ID: &quot; + device.getProductId());
Log.i(TAG,&quot;Interface count: &quot; + device.getInterfaceCount());
Log.i(TAG,&quot;---------------------------------------&quot;);
// Get interface details
for (int index = 0; index &lt; device.getInterfaceCount(); index++)
{
UsbInterface mUsbInterface = device.getInterface(index);
Log.i(TAG,&quot;  *****     *****&quot;);
Log.i(TAG,&quot;  Interface index: &quot; + index);
Log.i(TAG,&quot;  Interface ID: &quot; + mUsbInterface.getId());
Log.i(TAG,&quot;  Inteface class: &quot; + mUsbInterface.getInterfaceClass());
Log.i(TAG,&quot;  Interface protocol: &quot; + mUsbInterface.getInterfaceProtocol());
Log.i(TAG,&quot;  Endpoint count: &quot; + mUsbInterface.getEndpointCount());
// Get endpoint details 
for (int epi = 0; epi &lt; mUsbInterface.getEndpointCount(); epi++)
{
UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
Log.i(TAG,&quot;    ++++   ++++   ++++&quot;);
Log.i(TAG,&quot;    Endpoint index: &quot; + epi);
Log.i(TAG,&quot;    Attributes: &quot; + mEndpoint.getAttributes());
Log.i(TAG,&quot;    Direction: &quot; + mEndpoint.getDirection());
Log.i(TAG,&quot;    Number: &quot; + mEndpoint.getEndpointNumber());
Log.i(TAG,&quot;    Interval: &quot; + mEndpoint.getInterval());
Log.i(TAG,&quot;    Packet size: &quot; + mEndpoint.getMaxPacketSize());
Log.i(TAG,&quot;    Type: &quot; + mEndpoint.getType());
}
}
}
Log.i(TAG,&quot; No more devices connected.&quot;);
}

答案2

得分: 0

解决方案如果一切都不起作用:我使用了一个Arduino控制器,并将其焊接到按钮上。这并不是很复杂。

重要的是,控制器需要支持HID,例如带有ATmega32U4芯片的Leonardo Pro Micro。控制器的代码可以很容易地在谷歌上找到。

然后,可以使用override onKeyDown或onKeyUp等功能使其起作用。

英文:

The solution if nothings works: I got an arduino controller and solder it to the buttons. It's not that complicated.

Important is that the controller supports hid e.g. the leonardo pro micro with the atmega32u4 chip. The code for the controller can be found easily with google.

Then it works with override onKeyDown or onKeyUp etc.

huangapple
  • 本文由 发表于 2020年8月26日 23:33:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/63600942.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定