519 lines
17 KiB
C
519 lines
17 KiB
C
/***************************************************************************************************
|
|
**
|
|
** MODULE:
|
|
**
|
|
**
|
|
** DESCRIPTION:
|
|
**
|
|
**
|
|
** AUTHOR: Daniel Dean.
|
|
**
|
|
**
|
|
**
|
|
** CREATED:
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** (C) C O P Y R I G H T D A N I E L D E A N 1 9 9 6.
|
|
***************************************************************************************************/
|
|
#include <WINDOWS.H>
|
|
#include <string.h>
|
|
#include <hidsdi.h>
|
|
#include <hidusage.h>
|
|
#include "CLASS.H"
|
|
#include "IOCTL.H"
|
|
#include "resource.h"
|
|
|
|
/***************************************************************************************************
|
|
**
|
|
** IOCTLChannelDesc.
|
|
**
|
|
** DESCRIPTION:
|
|
**
|
|
** PARAMETERS:
|
|
**
|
|
** RETURNS:
|
|
**
|
|
***************************************************************************************************/
|
|
LPARAM IOCTLChannelDesc(HWND hWnd)
|
|
{
|
|
|
|
FARPROC lpfnProc;
|
|
HINSTANCE hInstance = (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE);
|
|
|
|
|
|
if((lpfnProc=(FARPROC)MakeProcInstance(ChannelDialogProc, hInstance)) != NULL)
|
|
{
|
|
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHANNELDIALOG), hWnd, lpfnProc,(LPARAM)hWnd);
|
|
FreeProcInstance(lpfnProc);
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
/***************************************************************************************************
|
|
**
|
|
** ChannelDialogProc()
|
|
**
|
|
** DESCRIPTION: Dialog Box procedure fot the Channel Info dialog
|
|
**
|
|
** PARAMETERS:
|
|
**
|
|
** RETURNS:
|
|
**
|
|
***************************************************************************************************/
|
|
BOOL CALLBACK ChannelDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static HWND hwndMama;
|
|
static PCHILD_INFO pChildInfo;
|
|
static ULONG Index = 0;
|
|
static BOOL fValues = TRUE; // Are we displaying 'Value' channels?
|
|
// If not we are displaying 'Button' channels
|
|
HANDLE hListBox;
|
|
char buff[32];
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
hwndMama = (HWND)lParam;
|
|
pChildInfo = (PCHILD_INFO)GetDeviceInfo(hwndMama);
|
|
SendMessage(hDlg,WM_COMMAND,IDC_NEXT,0);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch(wParam)
|
|
{
|
|
case IDOK:
|
|
EndDialog(hDlg,0);
|
|
return TRUE;
|
|
|
|
case IDC_NEXT:
|
|
hListBox = GetDlgItem(hDlg,IDC_ITEMLIST);
|
|
SendMessage(hListBox,LB_RESETCONTENT,0,0);
|
|
|
|
if( fValues )
|
|
{
|
|
wsprintf(buff,"Value Channel %d",Index);
|
|
SetWindowText(hDlg,buff);
|
|
|
|
if( Index < pChildInfo->NumValues )
|
|
{
|
|
|
|
wsprintf(buff,"UsagePage = %d",pChildInfo->pValueCaps[Index].UsagePage);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"ReportID = %d",pChildInfo->pValueCaps[Index].ReportID);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
if( pChildInfo->pValueCaps[Index].IsRange)
|
|
{
|
|
wsprintf(buff,"UsageMin = %d",pChildInfo->pValueCaps[Index].Range.UsageMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"UsageMax = %d",pChildInfo->pValueCaps[Index].Range.UsageMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"StringMin = %d",pChildInfo->pValueCaps[Index].Range.StringMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"StringMax = %d",pChildInfo->pValueCaps[Index].Range.StringMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"DesignatorMin = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"DesignatorMax = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(buff,"Usage = %d",pChildInfo->pValueCaps[Index].NotRange.Usage);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"StringIndex = %d",pChildInfo->pValueCaps[Index].NotRange.StringIndex);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"DesignatorIndex = %d",pChildInfo->pValueCaps[Index].NotRange.DesignatorIndex);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
}
|
|
if( pChildInfo->pValueCaps[Index].HasNull )
|
|
{
|
|
wsprintf(buff,"NULL = %d",pChildInfo->pValueCaps[Index].Null);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
}
|
|
wsprintf(buff,"LogicalMin = %d",pChildInfo->pValueCaps[Index].LogicalMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"LogicalMax = %d",pChildInfo->pValueCaps[Index].LogicalMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"PhysicalMin = %d",pChildInfo->pValueCaps[Index].PhysicalMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"PhysicalMax = %d",pChildInfo->pValueCaps[Index].PhysicalMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
|
|
Index++;
|
|
}
|
|
else
|
|
{
|
|
Index = 0;
|
|
fValues = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
if( Index < pChildInfo->NumButtons )
|
|
{
|
|
hListBox = GetDlgItem(hDlg,IDC_ITEMLIST);
|
|
wsprintf(buff,"Button Channel %d",Index);
|
|
SetWindowText(hDlg,buff);
|
|
|
|
wsprintf(buff,"UsagePage = %d",pChildInfo->pValueCaps[Index].UsagePage);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"ReportID = %d",pChildInfo->pValueCaps[Index].ReportID);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
if( pChildInfo->pValueCaps[Index].IsRange)
|
|
{
|
|
wsprintf(buff,"UsageMin = %d",pChildInfo->pValueCaps[Index].Range.UsageMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"UsageMax = %d",pChildInfo->pValueCaps[Index].Range.UsageMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"StringMin = %d",pChildInfo->pValueCaps[Index].Range.StringMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"StringMax = %d",pChildInfo->pValueCaps[Index].Range.StringMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"DesignatorMin = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMin);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"DesignatorMax = %d",pChildInfo->pValueCaps[Index].Range.DesignatorMax);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(buff,"Usage = %d",pChildInfo->pValueCaps[Index].NotRange.Usage);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"StringIndex = %d",pChildInfo->pValueCaps[Index].NotRange.StringIndex);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
wsprintf(buff,"DesignatorIndex = %d",pChildInfo->pValueCaps[Index].NotRange.DesignatorIndex);
|
|
SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)buff);
|
|
}
|
|
Index++;
|
|
}
|
|
else
|
|
{
|
|
fValues = TRUE;
|
|
Index = 0;
|
|
}
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
}//end case WM_COMMAND
|
|
|
|
|
|
}//end switch(uMsg)
|
|
|
|
return FALSE;
|
|
}
|
|
/***************************************************************************************************
|
|
**
|
|
** IOCTLDeviceDesc.
|
|
**
|
|
** DESCRIPTION:
|
|
**
|
|
** PARAMETERS:
|
|
**
|
|
** RETURNS:
|
|
**
|
|
***************************************************************************************************/
|
|
LPARAM IOCTLDeviceDesc(HWND hWnd)
|
|
{
|
|
return SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************************************
|
|
**
|
|
** IOCTLRead.
|
|
**
|
|
** DESCRIPTION:
|
|
**
|
|
** PARAMETERS:
|
|
**
|
|
** RETURNS:
|
|
**
|
|
***************************************************************************************************/
|
|
LPARAM IOCTLRead(HWND hWnd)
|
|
{
|
|
ULONG dwThreadID;
|
|
HANDLE hThread;
|
|
PREADTHREAD pThreadData;
|
|
|
|
|
|
OutputDebugString(">>>>HIDMON.EXE: IOCTLRead() Enter\n");
|
|
|
|
// If a read or a write is in progress stop it
|
|
if(GetThreadData(hWnd))
|
|
IOCTLStop(hWnd);
|
|
|
|
// Get the number of bytes of data for this device
|
|
|
|
|
|
// Allocate and setup a thread variables
|
|
pThreadData = (PREADTHREAD) GlobalAlloc(GPTR, sizeof(READTHREAD));
|
|
|
|
if(!pThreadData)
|
|
{
|
|
MessageBox(hWnd,"IOCTLRead(): GlobalAlloc fialed","Ooops!",MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
pThreadData->hEditWin = GetEditWin(hWnd);
|
|
pThreadData->ThisThread = TRUE;
|
|
pThreadData->hDevice = GetDeviceHandle(hWnd);
|
|
pThreadData->hWnd = hWnd;
|
|
// Create Data notification thread
|
|
hThread = CreateThread((LPSECURITY_ATTRIBUTES) NULL,
|
|
(DWORD) 0,
|
|
(LPTHREAD_START_ROUTINE) ReadWatch,
|
|
(LPVOID) pThreadData,
|
|
CREATE_SUSPENDED,
|
|
&dwThreadID);
|
|
if(!hThread)
|
|
{
|
|
GlobalFree(pThreadData);
|
|
MessageBox(hWnd,"IOCTLRead(): CreateThread fialed","Ooops!",MB_OK);
|
|
return FAILURE;
|
|
}
|
|
SetThreadData(hWnd, pThreadData);
|
|
|
|
// Set Thread priority and start thread
|
|
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
|
ResumeThread(hThread);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************************************
|
|
**
|
|
** IOCTLWrite.
|
|
**
|
|
** DESCRIPTION:
|
|
**
|
|
** PARAMETERS:
|
|
**
|
|
** RETURNS:
|
|
**
|
|
***************************************************************************************************/
|
|
LPARAM IOCTLWrite(HWND hWnd)
|
|
{
|
|
ULONG dwReturn = 0;
|
|
OVERLAPPED Overlapped;
|
|
|
|
|
|
// If a read or a write is in progress stop it
|
|
if(GetThreadData(hWnd))
|
|
IOCTLStop(hWnd);
|
|
|
|
// Need a way to get data froom user
|
|
// Need a way to get channel number from user
|
|
|
|
Overlapped.Offset = 3;
|
|
Overlapped.hEvent = NULL;
|
|
|
|
dwReturn = 0;
|
|
WriteFile(GetDeviceHandle(hWnd), (PVOID) "Hello", sizeof("Hello"), &dwReturn, &Overlapped);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/***************************************************************************************************
|
|
**
|
|
** IOCTLStop.
|
|
**
|
|
** DESCRIPTION:
|
|
**
|
|
** PARAMETERS:
|
|
**
|
|
** RETURNS:
|
|
**
|
|
***************************************************************************************************/
|
|
LPARAM IOCTLStop(HWND hWnd)
|
|
{
|
|
PREADTHREAD pThreadData;
|
|
|
|
OutputDebugString(">>>>HIDMON.EXE: IOCTLStop() Enter\n");
|
|
|
|
|
|
pThreadData = GetThreadData(hWnd);
|
|
|
|
if(pThreadData)
|
|
{
|
|
SetThreadData(hWnd, 0);
|
|
pThreadData->ThisThread = FALSE;
|
|
}
|
|
// Allow the thread to die
|
|
//Sleep(250);
|
|
|
|
OutputDebugString(">>>>HIDMON.EXE: IOCTLStop() Exit\n");
|
|
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** FUNCTION: ReadWatch()
|
|
**
|
|
** PURPOSE: Read next available packet and display in child window
|
|
**
|
|
**
|
|
**
|
|
*******************************************************************************/
|
|
#define MAX_CHARS_PER_LINE 128
|
|
|
|
VOID CALLBACK ReadWatch(HWND hWnd, UINT uMsg, UINT TimerID, DWORD dwTime)
|
|
{
|
|
PUCHAR WriteBuffer;
|
|
PUCHAR ReadBuffer;
|
|
ULONG NumChannels;
|
|
ULONG NumBytes;
|
|
ULONG LogicalReturn;
|
|
READTHREAD ThreadData;
|
|
OVERLAPPED OV;
|
|
PCHILD_INFO pChildInfo;
|
|
|
|
OutputDebugString(">>>>HIDMON.EXE: ReadWatch() Enter\n");
|
|
|
|
// Retrieve info for this child
|
|
pChildInfo = (PCHILD_INFO)GetDeviceInfo(hWnd);
|
|
|
|
NumChannels = pChildInfo->hidCaps->NumberInputValueCaps +
|
|
pChildInfo->hidCaps->NumberInputButtonCaps;
|
|
NumBytes = pChildInfo->hidCaps->InputReportByteLength;
|
|
|
|
|
|
// Allocate memory for our ReadBuffer
|
|
ReadBuffer = (PUCHAR) GlobalAlloc(GPTR,NumBytes);
|
|
if(!ReadBuffer)
|
|
return;// FALSE;
|
|
|
|
// Allocate memory for our 'screen' buffer
|
|
WriteBuffer = (PUCHAR) GlobalAlloc(GPTR,NumChannels*MAX_CHARS_PER_LINE);
|
|
if(!WriteBuffer)
|
|
{
|
|
GlobalFree(ReadBuffer);
|
|
return;// FALSE;
|
|
}
|
|
|
|
// Setup read buffer
|
|
memset(ReadBuffer, 0, NumBytes);
|
|
// Setup overlapped structure
|
|
memset(&OV, 0, sizeof(OVERLAPPED));
|
|
// Start read
|
|
LogicalReturn = ReadFileEx(GetDeviceHandle(hWnd),
|
|
(LPVOID) ReadBuffer,
|
|
NumBytes,
|
|
&OV,
|
|
NULL);
|
|
|
|
// Print error message if failed
|
|
if(!LogicalReturn)
|
|
SendMessage(ThreadData.hEditWin,
|
|
WM_SETTEXT,
|
|
(WPARAM) sizeof("ReadFile FAILED!"),
|
|
(LPARAM) "ReadFile FAILED!");
|
|
else
|
|
if( LogicalReturn )
|
|
{
|
|
PCHAR pChar = WriteBuffer;
|
|
NTSTATUS rc;
|
|
char tmpBuff[256],tmpBuff2[256];
|
|
ULONG i,Value;
|
|
|
|
|
|
//
|
|
// Parse the data from our last Read
|
|
//
|
|
|
|
// Clear the buffer
|
|
memset(WriteBuffer,'\0',NumChannels*MAX_CHARS_PER_LINE);
|
|
|
|
// Make Text strings
|
|
|
|
// First do the Value channels
|
|
for(i=0;i<pChildInfo->hidCaps->NumberInputValueCaps;i++)
|
|
{
|
|
|
|
rc = HidP_GetUsageValue(HidP_Input,
|
|
pChildInfo->pValueCaps[i].UsagePage,
|
|
0,
|
|
pChildInfo->pValueCaps[i].NotRange.Usage,
|
|
&Value,
|
|
pChildInfo->hidPPData,
|
|
ReadBuffer,
|
|
NumBytes );
|
|
|
|
wsprintf(tmpBuff,"Value: Usage[%02d]:[%02d] = %d\r\n",
|
|
pChildInfo->pValueCaps[i].UsagePage,
|
|
pChildInfo->pValueCaps[i].NotRange.Usage,
|
|
Value );
|
|
|
|
strcat(WriteBuffer,tmpBuff);
|
|
|
|
|
|
}
|
|
|
|
// Then do the button channels
|
|
for(i=0;i<pChildInfo->hidCaps->NumberInputButtonCaps;i++)
|
|
{
|
|
PUCHAR pUsageList;
|
|
DWORD ulUsageListLen;
|
|
//UCHAR TempBuff[256];
|
|
|
|
// Get the maximum usage list length
|
|
ulUsageListLen = HidP_MaxUsageListLength( HidP_Input,
|
|
pChildInfo->pButtonCaps[i].UsagePage,
|
|
pChildInfo->hidPPData );
|
|
|
|
pUsageList = (PUCHAR)GlobalAlloc(GMEM_FIXED,ulUsageListLen);
|
|
|
|
wsprintf( tmpBuff,"Buttons:[%02d]:[%02d] = ",pChildInfo->pButtonCaps[i].UsagePage,
|
|
pChildInfo->pButtonCaps[i].NotRange.Usage);
|
|
|
|
ulUsageListLen++;
|
|
rc = HidP_GetUsages(HidP_Input,
|
|
pChildInfo->pButtonCaps[i].UsagePage,
|
|
pChildInfo->pButtonCaps[i].LinkCollection,
|
|
pUsageList,
|
|
&ulUsageListLen,
|
|
pChildInfo->hidPPData,
|
|
ReadBuffer,
|
|
NumBytes );
|
|
|
|
// if Buttons are pressed
|
|
if( ulUsageListLen )
|
|
{
|
|
ULONG i;
|
|
for(i=0;i<ulUsageListLen;i++)
|
|
{
|
|
wsprintf(tmpBuff2,"0x%02X ",pUsageList[i]);
|
|
strcat(tmpBuff,tmpBuff2);
|
|
}
|
|
}
|
|
strcat(tmpBuff,"\r\n");
|
|
strcat(WriteBuffer,tmpBuff);
|
|
|
|
|
|
GlobalFree(pUsageList);
|
|
|
|
//i=pChildInfo->NumButtons;
|
|
}
|
|
|
|
SendMessage(GetEditWin(hWnd),//ThreadData.hEditWin,
|
|
WM_SETTEXT,
|
|
(WPARAM) strlen(WriteBuffer),
|
|
(LPARAM) WriteBuffer);
|
|
|
|
}// end if(LogicalReturn)
|
|
|
|
|
|
//
|
|
GlobalFree(ReadBuffer);
|
|
GlobalFree(WriteBuffer);
|
|
//TESTING!!
|
|
|
|
OutputDebugString(">>>>HIDMON.EXE: ReadWatch() Exit\n");
|
|
|
|
|
|
return;// TRUE;
|
|
}
|