如何从 Android 设备(响应者)生成自定义 MTP 事件,并在 Windows(发起者)中捕获事件
How do I generate custom MTP events from Android device (responder), and capture events in Windows (initiator)
我需要做的事情:
- 从响应者 (Beaglebone Black 运行 Android) 生成自定义供应商扩展事件,并在发起者中获取事件通知。
我用的是:
- 发起者 - Windows 7 上的 C# .Net 应用程序使用 portabledeviceapilib.dll(COM 互操作)库的托管包装器。
- Test Responder 1 - Microsoft 的 MTP Simulator 3.0
- 测试响应者 2 - Beaglebone Black 运行 Android Jelly Bean 4.1.1
我目前的工作:
我在发起者和响应者之间进行了成功的端到端通信。我可以发送 MTP 命令并获得 MTP 响应。我也成功地从响应者那里获得了标准事件通知。
问题
我在来自 Android 的 USB 数据包中没有看到 MTP 事件代码,即使事件已成功触发并被启动器接收。当我将 Android 中的标准事件代码更改为自定义偶数代码时,我仍然会收到相应的事件消息(详情如下)。
到目前为止我做了什么
在响应端,浏览Android源代码时,发现在/frameworks/av/media/mtp/mtp.h.[=中定义了MTP事件代码15=]
以下是为 adding/removing 对象定义的事件 ID。
#define MTP_EVENT_OBJECT_ADDED 0x4002
#define MTP_EVENT_OBJECT_REMOVED 0x4003
这些事件代码在 MTP 规范中定义。
为了订阅发起方的事件,我遵循文章 here by Darene Lewis. I am using the GUIDs for the events from the constants defined here 中的指南。
当文件添加到设备或从设备中删除文件时,会触发 MTP 事件通知,发起者会收到将 eventID 映射到常量之一的通知。据我了解,GUID的前4个字节对应于eventID。
以下是文件添加和删除事件的 GUID。
public static Guid WPD_EVENT_OBJECT_ADDED = new Guid( 0xA726DA95, 0xE207, 0x4B02, 0x8D, 0x44, 0xBE, 0xF2, 0xE8, 0x6C, 0xBF, 0xFC );
public static Guid WPD_EVENT_OBJECT_REMOVED = new Guid( 0xBE82AB88, 0xA52C, 0x4823, 0x96, 0xE5, 0xD0, 0x27, 0x26, 0x71, 0xFC, 0x38 );
我的测试包含来自设备的 adding/deleting 个文件。
使用模拟器时,发起者成功获取了两个事件通知,并且它们映射到上面定义的正确 WPD 事件。此外,我确认这些事件代码显示在 USB 数据包中。
当使用 Android 设备时,发起者成功获得两个事件通知,并且它们映射到正确的 WPD 事件,如上定义。但是,我在 USB 数据包中的任何地方都看不到事件代码。
我不明白 COM 互操作库如何成功收到事件通知,即使数据包不显示 MTP 事件代码。
因为我看不到数据包中的事件代码,所以我无法测试从设备向发起者发送自定义事件代码。
我通过修改上面指定的 Android MTP 事件代码为供应商扩展事件代码(如 MTP 规范中所述为 0xC000 - 0xC7FF)进行了实验,并更新了设备上的 libmtp 以查看什么会发生的。
我预计发起者永远不会收到事件,但令人惊讶的是,即使在更改事件代码之后,COM 互操作库仍然收到事件并将它们映射到正确的 GUID。
总而言之,在使用 Android 时,我 没有 在 USB 消息中看到 MTP 事件代码,尽管启动器以某种方式成功地获得了通知。使用 MTP 模拟器时,我确实在 USB 消息中看到了 MTP 事件代码。
我想出了解决办法。
似乎当您使用 OS(例如,add/delete 来自使用 Windows Explorer 的设备的文件)执行事件诱导操作时,事件被驱动程序吞没(WPD?USB?)虽然事件确实被触发了。即使当我使用硬件 USB 数据包分析器时,我也看不到事件数据包。当我使用设备本身引发事件时(MTP 模拟器,带有 Android 的 BeagleBone Black),数据包清晰可见。我不确定为什么连硬件分析器都不显示事件包。
为了解决我的问题(生成事件),我在 /frameworks/av/media/mtp/MtpServer.cpp 中创建了一个基于 sendEvent() 函数但使用自定义事件代码的覆盖函数, 它奏效了!
我需要做的事情:
- 从响应者 (Beaglebone Black 运行 Android) 生成自定义供应商扩展事件,并在发起者中获取事件通知。
我用的是:
- 发起者 - Windows 7 上的 C# .Net 应用程序使用 portabledeviceapilib.dll(COM 互操作)库的托管包装器。
- Test Responder 1 - Microsoft 的 MTP Simulator 3.0
- 测试响应者 2 - Beaglebone Black 运行 Android Jelly Bean 4.1.1
我目前的工作:
我在发起者和响应者之间进行了成功的端到端通信。我可以发送 MTP 命令并获得 MTP 响应。我也成功地从响应者那里获得了标准事件通知。
问题
我在来自 Android 的 USB 数据包中没有看到 MTP 事件代码,即使事件已成功触发并被启动器接收。当我将 Android 中的标准事件代码更改为自定义偶数代码时,我仍然会收到相应的事件消息(详情如下)。
到目前为止我做了什么
在响应端,浏览Android源代码时,发现在/frameworks/av/media/mtp/mtp.h.[=中定义了MTP事件代码15=]
以下是为 adding/removing 对象定义的事件 ID。
#define MTP_EVENT_OBJECT_ADDED 0x4002
#define MTP_EVENT_OBJECT_REMOVED 0x4003
这些事件代码在 MTP 规范中定义。
为了订阅发起方的事件,我遵循文章 here by Darene Lewis. I am using the GUIDs for the events from the constants defined here 中的指南。
当文件添加到设备或从设备中删除文件时,会触发 MTP 事件通知,发起者会收到将 eventID 映射到常量之一的通知。据我了解,GUID的前4个字节对应于eventID。
以下是文件添加和删除事件的 GUID。
public static Guid WPD_EVENT_OBJECT_ADDED = new Guid( 0xA726DA95, 0xE207, 0x4B02, 0x8D, 0x44, 0xBE, 0xF2, 0xE8, 0x6C, 0xBF, 0xFC );
public static Guid WPD_EVENT_OBJECT_REMOVED = new Guid( 0xBE82AB88, 0xA52C, 0x4823, 0x96, 0xE5, 0xD0, 0x27, 0x26, 0x71, 0xFC, 0x38 );
我的测试包含来自设备的 adding/deleting 个文件。
使用模拟器时,发起者成功获取了两个事件通知,并且它们映射到上面定义的正确 WPD 事件。此外,我确认这些事件代码显示在 USB 数据包中。
当使用 Android 设备时,发起者成功获得两个事件通知,并且它们映射到正确的 WPD 事件,如上定义。但是,我在 USB 数据包中的任何地方都看不到事件代码。
我不明白 COM 互操作库如何成功收到事件通知,即使数据包不显示 MTP 事件代码。
因为我看不到数据包中的事件代码,所以我无法测试从设备向发起者发送自定义事件代码。
我通过修改上面指定的 Android MTP 事件代码为供应商扩展事件代码(如 MTP 规范中所述为 0xC000 - 0xC7FF)进行了实验,并更新了设备上的 libmtp 以查看什么会发生的。
我预计发起者永远不会收到事件,但令人惊讶的是,即使在更改事件代码之后,COM 互操作库仍然收到事件并将它们映射到正确的 GUID。
总而言之,在使用 Android 时,我 没有 在 USB 消息中看到 MTP 事件代码,尽管启动器以某种方式成功地获得了通知。使用 MTP 模拟器时,我确实在 USB 消息中看到了 MTP 事件代码。
我想出了解决办法。
似乎当您使用 OS(例如,add/delete 来自使用 Windows Explorer 的设备的文件)执行事件诱导操作时,事件被驱动程序吞没(WPD?USB?)虽然事件确实被触发了。即使当我使用硬件 USB 数据包分析器时,我也看不到事件数据包。当我使用设备本身引发事件时(MTP 模拟器,带有 Android 的 BeagleBone Black),数据包清晰可见。我不确定为什么连硬件分析器都不显示事件包。
为了解决我的问题(生成事件),我在 /frameworks/av/media/mtp/MtpServer.cpp 中创建了一个基于 sendEvent() 函数但使用自定义事件代码的覆盖函数, 它奏效了!