1

我需要做什么:

  • 从响应者(运行 Android 的 Beaglebone Black)生成自定义供应商扩展事件,并在发起者中获取事件通知。

我正在使用什么:

  • Initiator - Windows 7 上的 C# .Net 应用程序,使用用于portabledeviceapilib.dll(COM 互操作)库的托管包装器。
  • 测试响应程序 1 - Microsoft 的 MTP 模拟器 3.0
  • 测试响应程序 2 - 运行 Android Jelly Bean 4.1.1 的 Beaglebone Black

到目前为止我所做的工作:

我在发起者和响应者之间进行了成功的端到端通信。我可以发送 MTP 命令并获得 MTP 响应。我还成功地从响应者那里获得了标准事件通知。

问题

我在来自 Android 的 USB 数据包中看不到 MTP 事件代码,即使事件已成功触发并由发起方接收。当我将 Android 中的标准事件代码更改为自定义偶数代码时,我仍然会收到相应的事件消息(详情如下)。

到目前为止我做了什么

在响应端,浏览 Android 源代码时,我发现/frameworks/av/media/mtp/mtp.h中定义了 MTP 事件代码。

以下是为添加/删除对象定义的 eventID。

#define MTP_EVENT_OBJECT_ADDED                      0x4002
#define MTP_EVENT_OBJECT_REMOVED                    0x4003

这些事件代码在 MTP 规范中定义。

为了订阅发起方的事件,我遵循Darene Lewis的文章中的指导方针。我将 GUID 用于此处定义的常量中的事件。

当向设备添加文件或从设备中删除文件时,将触发 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  );

我的测试包括从设备中添加/删除文件。

使用模拟器时,发起者成功获得两个事件通知,并且它们映射到如上定义的正确 WPD 事件。此外,我确认这些事件代码显示在 USB 数据包中。

使用 Android 设备时,发起者成功获取了两个事件通知,并且它们映射到如上定义的正确 WPD 事件。但是,我在 USB 数据包的任何地方都看不到事件代码。

我不明白 COM 互操作库如何成功收到事件通知,即使数据包不显示 MTP 事件代码。

由于我看不到数据包中的事件代码,因此无法测试将自定义事件代码从设备发送到发起方。

我做了一个实验,修改了上面为供应商扩展事件代码指定的 Android MTP 事件代码(如 MTP 规范中所述为 0xC000 - 0xC7FF),并更新设备上的 libmtp 以查看会发生什么。

我预计发起者永远不会收到事件,但令人惊讶的是,即使在更改事件代码之后,COM 互操作库仍然接收到事件并将它们映射到正确的 GUID。

总而言之,在使用 Android 时,我在 USB 消息中看不到 MTP 事件代码,尽管发起者以某种方式成功获取了通知。使用 MTP 模拟器时,我确实在 USB 消息中看到了 MTP 事件代码。

4

1 回答 1

1

我想出了解决方案。

似乎当您使用操作系统执行事件诱导操作(例如,使用 Windows 资源管理器从设备中添加/删除文件)时,事件被驱动程序(WPD?USB?)吞没,尽管事件确实被触发了。即使我使用硬件 USB 数据包分析器,我也看不到事件数据包。当我使用设备本身引发事件时(MTP 模拟器、BeagleBone Black 和 Android),数据包清晰可见。我不确定为什么连硬件分析器都不显示事件包。

为了解决我的问题(生成事件),我在 /frameworks/av/media/mtp/MtpServer.cpp 中创建了一个覆盖函数基于 sendEvent() 函数但使用自定义事件代码,并且它有效!

于 2015-10-12T14:12:34.973 回答