开发基于Cy68013的USB设备已经有一段时间,虽然知道它可以支持即插即用,但是一直没有去设计相关的代码,只是在MFC中设计了一个名为“USB连接”的按钮来手动连接到USB设备(参考《USB应用开发技术大全》薛园园编著 人民邮电出版社,2007)。最近又去翻看Cy68013的帮助文档,发现了支持插即用的相关代码,于是试验了一下,基本解决了基于Cy68013的USB设备的PnP功能。
在CyAPI的帮助文件中,对于提供的USB设备类CCyUSBDevice有一段这样的解释:
CCyUSBDevice::CCyUSBDevice(HANDLE hnd = NULL, GUID guid = CYUSBDRV_GUID)
* This is the constructor for the CCyUSBDevice class.
* It registers the window of hnd to receive USB Plug and Play messages when devices are onnected 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.
可见,在构建类的对象时给定其HANDLE之后便可以支持USB即插即用。
在CyAPI的帮助文件中还给出了代码示例(虽然是c++ Builder的代码,但对VC程序还是有借鉴作用的)。代码如下:
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
USBDevice = new CCyUSBDevice(Handle);
CurrentEndPt = USBDevice->ControlEndPt;
}
// Overload MainForm's WndProc method to watch for PnP messages
// Requires #include <dbt.h>
void __fastcall TMainForm::WndProc(TMessage &Message)
{
if (Message.Msg == WM_DEVICECHANGE) {
// Tracks DBT_DEVICEARRIVAL followed by DBT_DEVNODES_CHANGED
if (Message.WParam == DBT_DEVICEARRIVAL) {
bPnP_Arrival = true;
bPnP_DevNodeChange = false;
}
// Tracks DBT_DEVNODES_CHANGED followed by DBT_DEVICEREMOVECOMPLETE
if (Message.WParam == DBT_DEVNODES_CHANGED) {
bPnP_DevNodeChange = true;
bPnP_Removal = false;
}
if (Message.WParam == DBT_DEVICEREMOVECOMPLETE) {
bPnP_Removal = true;
PDEV_BROADCAST_HDR bcastHdr = (PDEV_BROADCAST_HDR) Message.LParam;
if (bcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
PDEV_BROADCAST_HANDLE pDev = (PDEV_BROADCAST_HANDLE) Message.LParam;
if (pDev->dbch_handle == USBDevice->DeviceHandle())
USBDevice->Close();
}
}
// If DBT_DEVNODES_CHANGED followed by DBT_DEVICEREMOVECOMPLETE
if (bPnP_Removal && bPnP_DevNodeChange) {
Sleep(10);
DisplayDevices();
bPnP_Removal = false;
bPnP_DevNodeChange = false;
}
// If DBT_DEVICEARRIVAL followed by DBT_DEVNODES_CHANGED
if (bPnP_DevNodeChange && bPnP_Arrival) {
DisplayDevices();
bPnP_Arrival = false;
bPnP_DevNodeChange = false;
}
}
TForm::WndProc(Message);
}
可以看出,程序通过重载WndProc来实现USB设备的相关通知(“Overload MainForm's WndProc method to watch for PnP messages ”), 而在VC下也是有这个函数的,仿照上述代码,可以编写代码如下:
LRESULT C**IDlg::WindowProc(UINT message,WPARAM wParam,LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
if (message == WM_DEVICECHANGE)
{
// Tracks DBT_DEVICEARRIVAL followed by DBT_DEVNODES_CHANGED
if (wParam == DBT_DEVICEARRIVAL)
{
bPnP_Arrival = true;
bPnP_DevNodeChange = false;
}
// Tracks DBT_DEVNODES_CHANGED followed by DBT_DEVICEREMOVECOMPLETE
if (wParam == DBT_DEVNODES_CHANGED)
{
bPnP_DevNodeChange = true;
bPnP_Removal = false;
}
if (wParam == DBT_DEVICEREMOVECOMPLETE)
{
bPnP_Removal = true;
// PDEV_BROADCAST_HDR bcastHdr = (PDEV_BROADCAST_HDR) lParam;
// if (bcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE)
{
// PDEV_BROADCAST_HANDLE pDev = (PDEV_BROADCAST_HANDLE) lParam;
// DEV_BROADCAST_HDR *stHDR;
// stHDR = (DEV_BROADCAST_HDR *)lParam;
//if (pDev->dbch_handle == USBDevice->DeviceHandle()) //判断设备类型
//if (stHDR->dbch_handle == USBDevice->DeviceHandle())
// USBDevice->Close();
}
}
// If DBT_DEVNODES_CHANGED followed by DBT_DEVICEREMOVECOMPLETE
if (bPnP_Removal && bPnP_DevNodeChange)
{
Sleep(10);
DisplayDevices();
bPnP_Removal = false;
bPnP_DevNodeChange = false;
}
// If DBT_DEVICEARRIVAL followed by DBT_DEVNODES_CHANGED
if (bPnP_DevNodeChange && bPnP_Arrival)
{
DisplayDevices();
bPnP_Arrival = false;
bPnP_DevNodeChange = false;
}
}
return CDialog::WindowProc(message,wParam,lParam);
}
然而该段代码并没有指明产生USB消息的设备类型,因此任何USB设备的插拔都会引起程序的相应,为了准确识别到Cy68013的USB设备特别编写了代码中加粗的DisplayDevices(),代码如下:
void CECHWorkStationIIDlg::DisplayDevices()
{
if(USBDevice->IsOpen())
{
USBDevice->Open(0);
if(!USBDevice->IsOpen())
{
USBDevice->Close();
m_USBStatus = "未连接到仪器";
UpdateData(FALSE);
// MessageBox("USB设备移除。/n","USB connect",MB_OK|MB_ICONERROR);
}
}
else
{
USBDevice->Open(0);
if(USBDevice->IsOpen())
{
m_USBStatus = USBDevice->DeviceName;
UpdateData(FALSE);
if(USBDevice->DeviceCount()>1)
MessageBox("应用程序不支持多台仪器同时连接到电脑。/n请移除不必要的仪器!/n","出错",MB_OK|MB_ICONERROR);
}
}
}
这样就实现了CY68013设备的热插拔。
上述内容只是提供了一种解决CY68013 USB设备的一种方法。更多方法欢迎大家一起讨论!