Cypress-USB-PnP事件注册方法

来源:互联网 发布:fl软件下载 编辑:程序博客网 时间:2024/05/17 08:52

首先,我们先来看一段API描述

CCyUSBDevice::CCyUSBDevice(HANDLE hnd = NULL, GUID guid = CYUSBDRV_GUID)

Description
This is the constructor for the CCyUSBDevice class.
It registers the window of hnd to receive USB Plug and Play messages when devices are connected or disconnected to/from the driver.

The object created serves as the programming interface to the driver whose GUID is passed in the guid parameter.

The constructor initializes the class members and then calls the Open(0) method to open the first device that is attached to the driver.

Parameters

hnd

hnd is a handle to the application’s main window (the window whose WndProc function will process USB PnP events).

If you are building a console application or do not want your window to receive PnP events, you may omit the hnd parameter.

guid

guid is the GUID defined in the [Strings] section of the CyUsb.inf file (or your own named copy). If this parameter is omitted, guid defaults to CYUSBDRV_GUID.

If you do not want to register for PnP events, but you do want to pass your own driver GUID to the constructor, you will need to pass NULL as the hnd parameter.

引入本篇文章的两个猪脚,hnd和guid,根据描述大致可以获取以下信息:

  1. hnd是应用程序主窗体的handle,对应窗体的WndProc函数将处理USB-PnP-Event。
  2. guid参数是定义在CyUsb.inf文件中的[Strings]字段的数值,缺省的字段为CYUSBDRV_GUID。

和往常一样,操作系统相关的说明,即使知道了含义,也不明觉厉,需要做相关测试来验证自己的猜测。根据以上信息,查阅了相关资料,有了如下的测试用例:

  1. 如果CCyUSBDevice不传入handle时,是不是就不会得到相关信息。
  2. 如果CCyUSBDevice传入handle后,在PlugIN和PlugOut时分别会出现什么事件?
  3. guid具体起到什么作用?

情况一和情况二综合测试:

  1. 如果CCyUSBDevice不传入handle时,是不是就不会得到相关信息。
  2. 如果CCyUSBDevice传入handle后,在PlugIN和PlugOut时分别会出现什么事件?

参考windows官方文档
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363215(v=vs.85).aspx
中对wParam表格定义

wParam
The event that has occurred. This parameter can be one of the following values from the Dbt.h header file.

根据文档中的例程代码,将代码做如下修改:

void MainForm::WndProc(Message &Message){    if (Message.Msg == WM_DEVICECHANGE)    {        printf(%x, Message.WParam); //! 查看DEVICECHANGE-对应到来的消息参数    }}

PlugIN输出结果:

7

DBT_DEVNODES_CHANGED 消息

PlugOUT输出结果:

7
7

DBT_DEVNODES_CHANGED 消息
DBT_DEVNODES_CHANGED 消息


当设置handle后,PlugIN和PlugOUT事件如下
设置handle后-PlugIN输出结果:

7
8000
7
7

查表可知:
DBT_DEVNODES_CHANGED 消息
DBT_DEVICEARRIVAL 消息
DBT_DEVNODES_CHANGED 消息
DBT_DEVNODES_CHANGED 消息

设置handle后-PlugOUT输出结果:

8004
8004
7

查表可知:
DBT_DEVICEREMOVECOMPLETE 消息
DBT_DEVICEREMOVECOMPLETE 消息
DBT_DEVNODES_CHANGED 消息

引用windows手册上关于上述两个新的事件解释说明:

DBT_DEVICEARRIVAL
0x8000
A device or piece of media has been inserted and is now available.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363205(v=vs.85).aspx

DBT_DEVICEREMOVECOMPLETE
0x8004
A device or piece of media has been removed.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363208(v=vs.85).aspx

根据手册可以得知上述两个事件表示插入和移除事件描述。
上述两个事件的lParam参数描述一致

The structure consists of an event-independent header, followed by event-dependent members that describe the device. To use this structure, treat the structure as a DEV_BROADCAST_HDR structure, then check its dbch_devicetype member to determine the device type.

大意为,可以通过DEV_BROADCAST_HDRdbch_devicetype 字段判断设备类型,然后通过具体类型枚举真实的结构体类型,例如当dbch_devicetypeDBT_DEVTYP_HANDLE可以将lParam转换为DEV_BROADCAST_HANDLE结构体。
详见下表

这里写图片描述

根据实际测试可以得到如下信息:
插入时,到来的消息是:
DBT_DEVICEARRIVAL
dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE

拔出时,到来的消息时:
DBT_DEVICEREMOVECOMPLETE
dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE
DBT_DEVICEREMOVECOMPLETE
dbch_devicetype = DBT_DEVTYP_HANDLE

DBT_DEVTYP_DEVICEINTERFACE 消息中值得关注的字段为
dbcc_classguid,该字段数据和CCyUSBDevice注册的guid值相同

DBT_DEVTYP_HANDLE 消息中dbch_handle,该字段和CCyUSBDevice对象中DeviceHandle()相同


刚才假设如果未传入窗体句柄时,拔出和插入时,都只会出现DBT_DEVNODES_CHANGED 消息,因为具体的事件并未投递到窗体中来。

情况一和二结论:
当不传入handle时,可以检测到节点有所变化,但无法判断是哪个设备发生具体什么事件。而传入handle可以根据DBT_DEVICEREMOVECOMPLETE 事件中的classguid信息来枚举是何种设备,由dbch_handle信息来判断是第几个设备退出。


情况三

guid具体起到什么作用?

我们可以尝试构造CCyUSBDevice时传入一份与CyUsb.inf文件中[String]字段不同的GUID值,最后得到如下结论:
和不传入handle一样,设备未成功注册,本人还猜测甚至都无法正常的usb通信,因为与驱动文件中的GUID不符。
那么,实际上GUID的作用就是用于区分是何种设备,如果同样适用Cypress的3014芯片,不修改CyUsb.inf文件,就会引起两块不同的产品接入计算机或者拔出计算机,将会导致应用程序无法识别的两块产品的尴尬

扩展:
1. 当同一类产品,同时插入两个设备,那么将会出现2对拔插事件。
2. 当同一类产品,插入一个设备,但同时创建两个CCyUSBDevice设备,会出现一对拔插事件。但移除事件时,DBT_DEVICEREMOVECOMPLETEDBT_DEVTYP_DEVICEINTERFACE事件会到来一次,而DBT_DEVICEREMOVECOMPLETEDBT_DEVTYP_HANDLE会到来两次,因为对应的dbch_handle包含两个。