Skip to content

Instantly share code, notes, and snippets.

@taxilian
Created December 16, 2011 18:24
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taxilian/1487248 to your computer and use it in GitHub Desktop.
Save taxilian/1487248 to your computer and use it in GitHub Desktop.
Example of receiving WM_DEVICECHANGE in a plugin
#include <set>
#include "USBNotify.h"
USBNotify::USBNotify()
{
}
USBNotify::~USBNotify()
{
}
void USBNotify::NotifyDeviceChange()
{
boost::recursive_mutex::scoped_lock _l(m_mutex);
bool hasDevice = false; // TODO: detect if the device has changed
APIList::iterator it = weakApiList.begin();
APIList::iterator it_end = weakApiList.end();
while (it != it_end) {
USBNotifyAPIPtr ptr(it->lock());
if (!ptr) {
// Remove any expired API pointers
it = weakApiList.erase(it);
} else {
ptr->fire_changed(hasDevice);
++it;
}
}
}
#pragma once
#ifndef H_USBNotify_
#define H_USBNotify_
#include <list>
#include <boost/noncopyable.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include "FBPointers.h"
FB_FORWARD_PTR(USBNotifyAPI);
class USBNotify: boost::noncopyable {
public:
typedef std::list<USBNotifyAPIWeakPtr> APIList;
USBNotify();
virtual ~USBNotify();
static USBNotify* create();
void NotifyDeviceChange();
void registerAPI(const USBNotifyAPIPtr& api) {
boost::recursive_mutex::scoped_lock _l(m_mutex);
weakApiList.push_back(api);
}
void unregisterAPI(const USBNotifyAPIPtr& api) {
boost::recursive_mutex::scoped_lock _l(m_mutex);
APIList::iterator it = weakApiList.begin();
APIList::iterator it_end = weakApiList.end();
while (it != it_end) {
USBNotifyAPIPtr ptr(it->lock());
if (!ptr || ptr == api) {
it = weakApiList.erase(it);
} else {
++it;
}
}
}
protected:
APIList weakApiList;
boost::recursive_mutex m_mutex;
};
#endif
#include "win_common.h"
#include "Win/WinMessageWindow.h"
#include <dbt.h>
#include <boost/bind.hpp>
#include "USBNotifyWin.h"
#include "logging.h"
static const GUID usb_hid = { 0xA5DCBF10L, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
USBNotify* USBNotify::create()
{
return new USBNotifyWin();
}
USBNotifyWin::USBNotifyWin()
{
m_window.setWinProc(boost::bind(&USBNotifyWin::WinProc, this, _1, _2, _3, _4, _5));
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = usb_hid;
hDeviceNotify = RegisterDeviceNotification(
m_window.getHWND(), // events recipient
&NotificationFilter, // type of device
DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle
);
if ( hDeviceNotify == NULL )
{
LPTSTR lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
FBLOG_ERROR("USBNotifyWin", "Could not register for device notification: " << lpMsgBuf);
LocalFree(lpMsgBuf);
}
}
USBNotifyWin::~USBNotifyWin()
{
UnregisterDeviceNotification(hDeviceNotify);
}
bool USBNotifyWin::WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult )
{
switch(uMsg) {
case WM_DEVICECHANGE:
{
//
// This is the actual message from the interface via Windows messaging.
// This code includes some additional decoding for this particular device type
// and some common validation checks.
//
// Note that not all devices utilize these optional parameters in the same
// way. Refer to the extended information for your particular device type
// specified by your GUID.
//
PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam;
// Output some messages to the window.
switch (wParam)
{
case DBT_DEVICEARRIVAL:
FBLOG_INFO("USBNotifyWin", "Device arrived");
break;
case DBT_DEVICEREMOVECOMPLETE:
FBLOG_INFO("USBNotifyWin", "Device removal complete");
break;
case DBT_DEVNODES_CHANGED:
FBLOG_INFO("USBNotifyWin", "Device nodes changed");
break;
default:
FBLOG_WARN("USBNotifyWin", "WM_DEVICECHANGE received");
break;
}
NotifyDeviceChange();
}
break;
}
return false;
}
#pragma once
#ifndef H_USBNotifyWin_
#define H_USBNotifyWin_
#include <list>
#include <boost/noncopyable.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include "FBPointers.h"
#include "../USBNotify.h"
namespace FB { class WinMessageWindow; };
class USBNotifyWin : public USBNotify {
public:
typedef std::list<USBNotifyAPIWeakPtr> myAPIList;
USBNotifyWin();
virtual ~USBNotifyWin();
bool WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult);
protected:
FB::WinMessageWindow m_window;
HDEVNOTIFY hDeviceNotify;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment