【问题标题】:How to catch signals from a unknown USB OTG device?如何捕获来自未知 USB OTG 设备的信号?
【发布时间】:2020-08-26 15:33:16
【问题描述】:

我有一个类似于鼠标的 USB OTG 设备,是在中国购买的,关于所用控制器的信息不多。当我将它连接到我的 android 时,有一个鼠标光标,并且该设备有 5 个硬按钮(左、右、上、下、输入)。我想对我的应用程序的按钮进行编程以执行特定任务。所以我需要读取输入信号并覆盖它们。

如何捕捉信号?

我找到了供应商 (0x04D9) 和产品 ID (0x2519) 以及控制器名称 Lenovo Calliope USB 键盘。但是不知道用过的芯片,很隐蔽。

它不适用于onKeyDowndispatchKeyEvent 方法。也不适用于USB serial Lib,因为没有使用提供的 VID 和 PID 找到/识别设备(请参阅下面与 Fatih Şennik 的讨论,其他设备也可以识别)。

我目前的假设是我无法获得信号是硬件/芯片问题。但奇怪的是,该设备在其他方面做了它应该做的事情。

【问题讨论】:

    标签: java android usb-otg


    【解决方案1】:

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

    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, "UTF-8");
                    data.concat("/n");
                    switch() // etc
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        };
    

    让我们首先尝试将我们的 android 手机连接到 USB otg 设备。至于产品和供应商 ID,您可以在将其插入 PC 时找到它。如果建立了连接,那么剩下的就来了。如果您能在此处分享 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 隐藏设备,尝试此代码可能会有所帮助;

    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,"---------------------------------------");
       // Get interface details
            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());
        // Get endpoint details 
                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.");
    }
    

    【讨论】:

    • 感谢您的回答!你能提供更多的上下文吗?我实现了库,但我无法覆盖 onReceivedData..
    • 不错。这是我在中国购买的设备,所以这是我的问题,我没有太多关于使用过的控制器的信息。但在您的帮助下,我发现他们使用带有 HID\VID_04D9&PID_2519&REV_0001&MI_00 的键盘和 MI_01&Col01 的鼠标的“Lenovo Calliope USB 键盘”控制器。所以我认为我的供应商 ID 是 0x04D9 而我的产品 ID 是 0x2519?当我插入这个时,我仍然得到没有找到设备的吐司......
    • 这很奇怪。如果已连接,设备和按钮工作正常,但我没有通过您的代码和我的 ID 获得设备信息。我仔细检查了一遍,我使用了一个从连接设备中读取供应商和产品 ID 的应用程序。仍然没有检测到。所以我尝试了另一只罗技的鼠标,它可以工作。我得到了 id 和你的代码,我得到了设备名称......我猜这是硬件问题?!
    • Hımm 是的,这可能与中国鼠标的 USB 转串口转换器芯片有关,他们可能正在使用除应用程序 FTDI FT232R、FT232H、FT2232H、FT4232H、FT230X、FT231X 支持的芯片之外的其他芯片, FT234XD、Prolific PL2303、Silabs CP2102、CP2105、秦恒CH340、CH341A。如果您找到他们正在使用的 USB 串行芯片。您可以下载他们的驱动程序并更新 GitHub 存储库或发送拉取请求。
    • 感谢您的努力。我拆开了它,芯片是隐蔽的,我不能在不破坏电路板的情况下将其移除。板上唯一的信息是 LKT-418 20190630。最后一个可能是生产日期,第一部分是一些内部编号,但没有有用的谷歌结果......我会再坚持一段时间,但最终我必须将我自己的控制器焊接到按钮上。
    【解决方案2】:

    如果没有任何效果,解决方案:我有一个 arduino 控制器并将其焊接到按钮上。没那么复杂。

    重要的是控制器支持隐藏,例如带有 atmega32u4 芯片的 leonardo pro micro。控制器的代码用google很容易找到。

    然后它可以覆盖 onKeyDown 或 onKeyUp 等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      相关资源
      最近更新 更多