【转】簡單講講 USB Human Interface Device
原地址http://213style.blogspot.com/2013/09/usb-human-interface-device.html
恩,發本文的原因是看到了以前畢業的朋友在旁邊的對話框問了一些問題,我想這些問題
Report Size (8) | 75 08 |
Report Count (8) | 95 08 |
Logical Maximum (255) | 26 FF 00 |
Report ID (50) | 85 32 |
Usage (Vendor-Defined 195) | 09 C3 |
Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Buf) |
B2 02 01 |
#include "stdafx.h"
#include "HIDGet.h"
#include "HIDGetDlg.h"
#include "Process.h" #ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif #define WM_THREADDATA WM_USER + 1
#define WM_READDATA WM_USER + 2 /////////////////////////////////////////////////////////////////////////////
// CHIDGetDlg dialog
struct _ThreadData
{
HWND hWnd;
HANDLE hDev;
char cBuf[9];
HANDLE hReadFinished;
}ThreadData; LRESULT CALLBACK ReadThreadWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
BOOL bRet; ResetEvent(ThreadData.hReadFinished);
OVERLAPPED ol;
ol.hEvent = ThreadData.hReadFinished;
ol.Offset = 0;
ol.OffsetHigh = 0; DWORD wResult, wByteRead;
switch(msg)
{
case WM_CLOSE:
CancelIo(ThreadData.hDev);
CloseHandle(ThreadData.hReadFinished);
DestroyWindow(hWnd);
break; case WM_DESTROY:
PostQuitMessage(0);
break; case WM_READDATA:
//ReadFile(ThreadData.hDev, ThreadData.cBuf, 9, &wByteRead, &ol);
ThreadData.cBuf[0] = 50;
bRet = HidD_GetFeature(ThreadData.hDev, ThreadData.cBuf, 9);
//wResult = WaitForSingleObject(ThreadData.hReadFinished, 1000);
if(/*wResult == WAIT_OBJECT_0*/ bRet == TRUE)
::PostMessage(ThreadData.hWnd, WM_THREADDATA, 0, 0);
else if(/*wResult == WAIT_TIMEOUT*/ bRet == FALSE)
::PostMessage(hWnd, WM_READDATA, 0, 0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
} return 0;
} void ReadThread(CHIDGetDlg* pDlg)
{
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0 ;
wndclass.hbrBackground = NULL;
wndclass.hCursor = NULL;
wndclass.hIcon = NULL;
wndclass.hIconSm = NULL;
wndclass.hInstance = GetModuleHandle(NULL);
wndclass.lpfnWndProc = ReadThreadWindowProc;
wndclass.lpszClassName = "ReadThread";
wndclass.lpszMenuName = NULL;
wndclass.style = 0 ;
RegisterClassEx(&wndclass); HWND hReadThreadWindow = ::CreateWindow("ReadThread", "", WS_POPUP,
0, 0, 0, 0, NULL, NULL,
GetModuleHandle(NULL), NULL);
pDlg->SetReadThreadHWND(hReadThreadWindow);
ThreadData.hReadFinished = CreateEvent(NULL, TRUE, FALSE, NULL);
SetEvent(pDlg->m_hReadThreadCreated); // Start the message loop
MSG msg;
while(GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} CHIDGetDlg::CHIDGetDlg(CWnd* pParent /*=NULL*/) : CDialog(CHIDGetDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CHIDGetDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CHIDGetDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CHIDGetDlg)
DDX_Control(pDX, IDC_DATA_ED, m_edData);
//}}AFX_DATA_MAP
} BEGIN_MESSAGE_MAP(CHIDGetDlg, CDialog)
//{{AFX_MSG_MAP(CHIDGetDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP() /////////////////////////////////////////////////////////////////////////////
// CHIDGetDlg message handlers void CHIDGetDlg::SetReadThreadHWND(HWND hWnd)
{
m_hReadThread = hWnd;
} void CHIDGetDlg::CreateReadThread()
{
ThreadData.hWnd = m_hWnd;
m_hReadThreadCreated = CreateEvent(NULL, TRUE, FALSE, NULL);
if(m_hReadThreadCreated)
{
DWORD threadID;
if(_beginthreadex(NULL, 0, (unsigned int (WINAPI*)(PVOID))ReadThread,
this, 0, (unsigned int*)&threadID) != 0)
WaitForSingleObject(m_hReadThreadCreated, INFINITE); CloseHandle(m_hReadThreadCreated);
}
} BOOL CHIDGetDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here
GetDeviceHandle();
CreateReadThread();
::PostMessage(m_hReadThread, WM_READDATA, 0, 0); return TRUE; // return TRUE unless you set the focus to a control
} // If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework. void CHIDGetDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
} // The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CHIDGetDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
} HANDLE CHIDGetDlg::GetDeviceHandle(GUID guid, HANDLE hDev, DWORD wDevice)
{
SP_DEVICE_INTERFACE_DATA interfaceDev;
interfaceDev.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); //Get interface
DWORD wSize = 0;
if(!SetupDiEnumDeviceInterfaces(hDev, NULL, &guid, wDevice, &interfaceDev)
|| SetupDiGetDeviceInterfaceDetail(hDev, &interfaceDev, NULL, 0, &wSize, NULL))
return INVALID_HANDLE_VALUE; //Create buffer
SP_INTERFACE_DEVICE_DETAIL_DATA *pDeviceDetail;
pDeviceDetail = (SP_INTERFACE_DEVICE_DETAIL_DATA*)malloc(wSize);
pDeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); if(!SetupDiGetDeviceInterfaceDetail(hDev, &interfaceDev, pDeviceDetail, wSize, &wSize, NULL))
{
free(pDeviceDetail);
return INVALID_HANDLE_VALUE;
} //Get device handle
HANDLE hDevice = CreateFile(pDeviceDetail->DevicePath, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL); free(pDeviceDetail);
return hDevice;
} void CHIDGetDlg::Show(CString str,long n)
{
CString strN;
strN.Format("%d", n);
m_edData.ReplaceSel(str + ":" + strN + "\r\n");
} void CHIDGetDlg::Show(CString str, CString s)
{
m_edData.ReplaceSel(str + ": " + s + "\r\n");
} void CHIDGetDlg::Clear()
{
int nStart, nStop;
m_edData.GetSel(nStart, nStop);
m_edData.SetSel(0, nStop);
m_edData.Clear();
} void CHIDGetDlg::GetDeviceHandle()
{
//Get HID GUID
GUID guid;
HidD_GetHidGuid(&guid); //Get all present HID interface
HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL,
DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if(hDeviceInfo == INVALID_HANDLE_VALUE) return; Clear();
DWORD w = 0;
while(1) /*for(DWORD w=0; w<20; w++)*/
{
if((ThreadData.hDev = GetDeviceHandle(guid, hDeviceInfo, /*w*/w++))!=INVALID_HANDLE_VALUE)
{
HIDD_ATTRIBUTES att;
if(HidD_GetAttributes(ThreadData.hDev, &att))
{
PHIDP_PREPARSED_DATA pPreData;
if(HidD_GetPreparsedData(ThreadData.hDev, &pPreData))
{
HIDP_CAPS cap;
if(HidP_GetCaps(pPreData, &cap)==HIDP_STATUS_SUCCESS)
{
if(att.VendorID==0x056D && att.ProductID==0x0002 && att.VersionNumber==0x7530)
{
if(cap.Usage==0x01 && cap.UsagePage==0x80)
{
HidD_FreePreparsedData(pPreData);
break;
}
}
}
HidD_FreePreparsedData(pPreData);
}
}
CloseHandle(ThreadData.hDev);
ThreadData.hDev = INVALID_HANDLE_VALUE;
} if(w > 65536)
{
CloseHandle(ThreadData.hDev);
ThreadData.hDev = INVALID_HANDLE_VALUE;
break;
}
} SetupDiDestroyDeviceInfoList(hDeviceInfo);
} void CHIDGetDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
::SendMessage(m_hReadThread, WM_CLOSE, 0, 0);
if(ThreadData.hDev!=INVALID_HANDLE_VALUE)
CloseHandle(ThreadData.hDev); CDialog::OnClose();
} LRESULT CHIDGetDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
static long nCount = 0; if(message == WM_THREADDATA)
{
CString str;
str.Format("# of packet = %d, report id =%d, LCD = %c %c %c %c %c %c %c %c",
nCount++,
ThreadData.cBuf[0], // report id = 50
ThreadData.cBuf[1],
ThreadData.cBuf[2],
ThreadData.cBuf[3],
ThreadData.cBuf[4],
ThreadData.cBuf[5],
ThreadData.cBuf[6],
ThreadData.cBuf[7],
ThreadData.cBuf[8]); Show("Data", str);
if(nCount > 500)
{
Clear();
nCount = 0;
} ::PostMessage(m_hReadThread, WM_READDATA, 0, 0);
} return CDialog::DefWindowProc(message, wParam, lParam);
}
case WM_READDATA:
//ReadFile(ThreadData.hDev, ThreadData.cBuf, 9, &wByteRead, &ol);
ThreadData.cBuf[0] = 50;
bRet = HidD_GetFeature(ThreadData.hDev, ThreadData.cBuf, 9);
//wResult = WaitForSingleObject(ThreadData.hReadFinished, 1000);
if(/*wResult == WAIT_OBJECT_0*/ bRet == TRUE)
::PostMessage(ThreadData.hWnd, WM_THREADDATA, 0, 0);
else if(/*wResult == WAIT_TIMEOUT*/ bRet == FALSE)
::PostMessage(hWnd, WM_READDATA, 0, 0);
break;
用 GetMessage 收到該訊息,相反的就是 Post 另外一個自訂訊息 WM_READDATA,這樣

就是你剛剛放進去的訊息,反正 GetMessage 輪詢個不停 總有會被處理到的時候。
事實上,主要我還有宣告一個隱形的視窗,然後才在這個隱形的視窗下的 WndProc 用訊息


Registering for Raw Input
Performing a Standard Read of Raw Input
Performing a Buffered Read of Raw Input
Performing a Standard Read of Raw Input
read of raw input from either a keyboard or mouse Human Interface Device
(HID) and then prints out various information from the device.
【转】簡單講講 USB Human Interface Device的更多相关文章
- Human Interface Device (HID) Class Decoder
http://www.usblyzer.com/usb-human-interface-device-hid-class-decoder.htm Human Interface Device (H ...
- [转]講講 John Carmack 的快速反平方根演算法
講講 John Carmack 的快速反平方根演算法 原地址http://213style.blogspot.com/2014/07/john-carmack.html 本篇的主題很簡單,講講怎麼快 ...
- 转:[ASP.NET]重構之路系列v4 – 簡單使用interface之『你也會IoC』
前言 上次v3版本,我們將Entity, Service, Dao, Utility都放到了類別庫裡面,讓我們可以輕鬆的在不同專案中用同一份組件.雖然文章沒有獲得太多的讚賞,不過相信那一定是太多人會這 ...
- [Xamarin] 簡單使用Fragment 靜態篇 (转帖)
新的Android 開發,非常會使用到Fragment,不過官方範例有點小複雜,對初學者來說有點難消化,所以就記錄一下心得,這邊部落格將使用靜態的方法使用Fragment,Fragment 有自己的生 ...
- 用JavaScript做一個簡單的計算器
今天繼續學習JavaScript,視頻講的確實挺差勁的.還是只能跟著W3School自己慢慢摸索著弄了.自己百度了一下,參考了一個大佬寫的一個簡單的計算器代碼.代碼能跑通,但是做出來的樣子實在是感覺太 ...
- 簡單工廠模式-之-什麼是產品線 And 抽象工廠模式-之-什麼是產品族
簡單工廠模式-之-什麼是產品線 簡單工廠模式中,有一個概念就是使用了多層次的產品結構,那麼什麼是產品結構或者說什麼是產品線? 假定我們有一個基準的產品標準Product,那麼所有繼承該基類或者傳遞基類 ...
- [Xamarin] 簡單使用AlertDialog (转帖)
這東西跟Toast 很像,有方便提示的作用 像是Windows 上面的MessageBox 或是 Javascript 的 Alert 會先阻斷使用者並且下一個決定 很簡單我就不贅述,基本上透過 Al ...
- 簡單SQL存儲過程實例
簡單SQL存儲過程實例 摘自:http://blog.csdn.net/libra6956/article/details/5589173 实例1:只返回单一记录集的存储过程. 银行存款表(bankM ...
- 【译】iOS人性化界面指南(iOS Human Interface Guidelines)(一)
1. 引言1.1 译者自述 我是一个表达能力一般的开发员,不管是书面表达,还是语言表达.在很早以前其实就有通过写博客锻炼这方面能力的想法,但水平有限实在没有什么拿得出手的东西分享.自2015年7月以来 ...
随机推荐
- bzoj4480: [Jsoi2013]快乐的jyy
[问题描述] 给定两个字符串A和B,表示JYY的两个朋友的名字.我们用A(i,j)表示A 字符串中从第i个字母到第j个字母所组成的子串.同样的,我们也可以定义B(x,y). JYY发现两个朋友关系的紧 ...
- Unable to load native-hadoop library for your platform... using builtin-java classes where applicable(四十四)
问题描述: Unable to load native-hadoop library for your platform... using builtin-java classes where app ...
- Dubbo(1)简介和Zookeeper安装
一.简介: Dubbo主页地址 http://dubbo.io/ Dubbo百度百科:https://baike.baidu.com/item/Dubbo/18907815?fr=aladdin 二 ...
- VLAN 及 GVRP 配置
一.VLAN配置 +进入vlan视图,如果指定的vlan没有创建则先创建它 [undo]vlan vlan_id undo vlan 剔除已创建的vlan VLAN_id:要进入的或要创建并进入的VL ...
- Jmeter(十)检查点
检查点又名断言,我们在手工测试过程中肉眼以及自己的逻辑思维对实际结果进行判断是否与预期结果一致,但是工具是死的,没有眼睛,没有思维,并不知道需要判断的信息在哪块,或者是来判断什么东西,我们需要让工具更 ...
- 使用adb安装遇到的一些坑
1.下载安装android SDK,可通过浏览器或者相关手机软件下载软件下载需要安装的apk安装文件,把apk文件放到android-sdk-windows\platform-tools下 2.可通过 ...
- [UE4]C++实现动态加载的问题:LoadClass<T>()和LoadObject<T>() 及 静态加载问题:ConstructorHelpers::FClassFinder()和FObjectFinder()
转自:http://aigo.iteye.com/blog/2281558 动态加载UObject和动态加载UClass分别用LoadObject<T>(),和LoadClass<T ...
- python运算符&优先性
(1)算数运算符: + - * / //(求整) %(求余) ** (2)比较运算符: > < > ...
- CS229 6.12 Neurons Networks from self-taught learning to deep network
self-taught learning 在特征提取方面完全是用的无监督的方法,对于有标记的数据,可以结合有监督学习来对上述方法得到的参数进行微调,从而得到一个更加准确的参数a. 在self-taug ...
- SPOJ COT3 - Combat on a tree
/* 考虑直接使用暴力来算的话 SG[i]表示以i为根的子树的SG值, 然后考虑枚举删除那个子树节点, 然后求拆成的树的sg异或值, 求mex即可 复杂度三次方 然后考虑尝试 整体来做 发现对于每次子 ...