如何从Android设备(响应者)生成自定义MTP事件,并在Windows中捕获事件(启动器)

时间:2015-10-08 19:00:13

标签: .net event-handling android-source mtp wpd

我需要做什么:

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

我正在使用的内容:

  • Initiator - Windows 7上的C#.Net应用程序,使用portabledeviceapilib.dll(COM互操作)库的托管包装。
  • 测试响应者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事件代码。

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

#define MTP_EVENT_OBJECT_ADDED                      0x4002
#define MTP_EVENT_OBJECT_REMOVED                    0x4003

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

对于订阅发起人方面的活动,我遵循Darene Lewis撰写的文章here中的指导原则。我正在使用GUID来定义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  );

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

使用模拟器时,启动器成功获取两个事件通知,并映射到上面定义的正确WPD事件。另外,我确认这些事件代码显示在USB数据包中。

使用Android设备时,启动器成功获取两个事件通知,并映射到上面定义的正确WPD事件。但是,我没有在USB数据包中的任何地方看到事件代码。

我不明白COM interop库如何成功通知事件,即使数据包没有显示MTP事件代码。

由于我无法在数据包中看到事件代码,因此无法测试从设备向启动器发送自定义事件代码。

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

我希望启动器永远不会获取事件,但令人惊讶的是,即使更改了事件代码,COM互操作库仍然会收到事件并将它们映射到正确的GUID。

总而言之,在使用Android时,我在USB消息中看到MTP事件代码,尽管启动器以某种方式成功获取通知。使用MTP模拟器时,我执行查看USB消息中的MTP事件代码。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。

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

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