|
|
/*++
Copyright (c) Microsoft 1998, All Rights Reserved
Module Name:
ecdisp.c
Abstract:
This module contains the code to handle the extended calls dialog box and the actions that can be performed in the dialog box.
Environment:
User mode
Revision History:
May-98 : Created
--*/
/*****************************************************************************
/* Extended call display include files
/*****************************************************************************/ #include <windows.h>
#include <limits.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <setupapi.h>
#include <vfw.h>
#include <assert.h>
#include "hidusage.h"
#include "hidsdi.h"
#include "hid.h"
#include "hclient.h"
#include "resource.h"
#include "buffers.h"
#include "ecdisp.h"
#include "strings.h"
#include <strsafe.h>
/*****************************************************************************
/* Local macro definitions for the supported function calls
/*****************************************************************************/
#define HID_DEVCALLS 20
#define HID_PPDCALLS 29
#define HID_NUMCALLS HID_DEVCALLS + HID_PPDCALLS
#define HIDD_GET_HID_GUID 1
#define HIDD_GET_FREE_PREPARSED_DATA 2
#define HIDD_GET_CONFIGURATION 3
#define HIDD_SET_CONFIGURATION 4
#define HIDD_FLUSH_QUEUE 5
#define HIDD_GET_ATTRIBUTES 6
#define HIDD_SET_FEATURE 7
#define HIDD_GET_FEATURE 8
#define HIDD_GET_INPUT_REPORT 9
#define HIDD_SET_OUTPUT_REPORT 10
#define HIDD_GET_NUM_INPUT_BUFFERS 11
#define HIDD_SET_NUM_INPUT_BUFFERS 12
#define HIDD_GET_PHYSICAL_DESCRIPTOR 13
#define HIDD_GET_MANUFACTURER_STRING 14
#define HIDD_GET_PRODUCT_STRING 15
#define HIDD_GET_INDEXED_STRING 16
#define HIDD_GET_SERIAL_NUMBER_STRING 17
#define HIDD_GET_MS_GENRE_DESCRIPTOR 18
#define HID_READ_REPORT 19
#define HID_WRITE_REPORT 20
#define HIDP_GET_BUTTON_CAPS 21
#define HIDP_GET_BUTTONS 22
#define HIDP_GET_BUTTONS_EX 23
#define HIDP_GET_CAPS 24
#define HIDP_GET_DATA 25
#define HIDP_GET_EXTENDED_ATTRIBUTES 26
#define HIDP_GET_LINK_COLL_NODES 27
#define HIDP_GET_SCALED_USAGE_VALUE 28
#define HIDP_GET_SPECIFIC_BUTTON_CAPS 29
#define HIDP_GET_SPECIFIC_VALUE_CAPS 30
#define HIDP_GET_USAGES 31
#define HIDP_GET_USAGES_EX 32
#define HIDP_GET_USAGE_VALUE 33
#define HIDP_GET_USAGE_VALUE_ARRAY 34
#define HIDP_GET_VALUE_CAPS 35
#define HIDP_INITIALIZE_REPORT_FOR_ID 36
#define HIDP_MAX_DATA_LIST_LENGTH 37
#define HIDP_MAX_USAGE_LIST_LENGTH 38
#define HIDP_SET_BUTTONS 39
#define HIDP_SET_DATA 40
#define HIDP_SET_SCALED_USAGE_VALUE 41
#define HIDP_SET_USAGES 42
#define HIDP_SET_USAGE_VALUE 43
#define HIDP_SET_USAGE_VALUE_ARRAY 44
#define HIDP_TRANSLATE_USAGES 45
#define HIDP_UNSET_BUTTONS 46
#define HIDP_UNSET_USAGES 47
#define HIDP_USAGE_LIST_DIFFERENCE 48
#define HID_CLEAR_REPORT 49
/*
// These two definitions are not used by the display routines since
// the two functions were molded together into one for purpose of execution
*/
#define HIDD_GET_PREPARSED_DATA 50
#define HIDD_FREE_PREPARSED_DATA 51
#define IS_HIDD_FUNCTION(func) (((func) >= HIDD_GET_HID_GUID) && \
((func) <= HIDD_GET_MS_GENRE_DESCRIPTOR))
#define IS_HIDP_FUNCTION(func) (((func) >= HIDP_GET_BUTTON_CAPS) && \
((func) <= HIDP_USAGE_LIST_DIFFERENCE))
#define IS_HID_FUNCTION(func) (((func) >= HID_READ_REPORT) && \
((func) <= HID_WRITE_REPORT))
#define IS_NOT_IMPLEMENTED(func) (((func) == HIDD_GET_CONFIGURATION) || \
((func) == HIDD_SET_CONFIGURATION) || \ ((func) == HIDP_TRANSLATE_USAGES) || \ (((func) == HIDP_INITIALIZE_REPORT_FOR_ID) && \ (NULL == pfnHidP_InitializeReportForID)) || \ (((func) == HIDP_GET_EXTENDED_ATTRIBUTES) && \ (NULL == pfnHidP_GetExtendedAttributes)))
/*****************************************************************************
/* Local macro definitions for buffer display sizes
/*****************************************************************************/
#define NUM_INPUT_BUFFERS 16
#define NUM_OUTPUT_BUFFERS 16
#define NUM_FEATURE_BUFFERS 16
/*****************************************************************************
/* Local macro definition for HidP_SetData dialog box
/*****************************************************************************/
#define SETDATA_LISTBOX_FORMAT "Index: %u, DataValue: %u"
/*****************************************************************************
/* Local macro definition for display output to output windows
/*****************************************************************************/
#define TEMP_BUFFER_SIZE 1024
#define OUTSTRING(win, str) SendMessage(win, LB_ADDSTRING, 0, (LPARAM) str)
#define OUTWSTRING(win, str) \
{ \ SIZE_T nBytes; \ \ nBytes = wcstombs(szTempBuffer, str, TEMP_BUFFER_SIZE-1); \ if ((SIZE_T) -1 == nBytes) { \ OUTSTRING(win, "Cannot convert wide-character string"); \ } \ else { \ szTempBuffer[nBytes] = '\0'; \ OUTSTRING(win, szTempBuffer); \ } \ }
#define DISPLAY_HIDD_STATUS(win, func, status, strret) \
{ \ strret = StringCbPrintf(szTempBuffer, \ TEMP_BUFFER_SIZE, \ "%s returned: %s", \ func, \ (status).IsHidError ? "FALSE" : "TRUE"); \ \ OUTSTRING(win, szTempBuffer); \ \ if ((status).IsHidError) { \ strret = StringCbPrintf(szTempBuffer, \ TEMP_BUFFER_SIZE, \ "ErrorCode: %d", \ GetLastError()); \ }\ OUTSTRING(win, szTempBuffer); \ }
#define DISPLAY_HIDP_STATUS(win, func, status, strret) \
{ \ strret = StringCbPrintf(szTempBuffer, \ TEMP_BUFFER_SIZE, \ "%s returned: %s", \ func, \ ECDisp_GetHidAppStatusString(status.HidErrorCode)); \ \ OUTSTRING(win, szTempBuffer); \ }
#define ECDISP_ERROR(win, msg) \
{ \ MessageBox(win, \ msg, \ HCLIENT_ERROR, \ MB_ICONEXCLAMATION); \ }
#define GET_FUNCTION_NAME(index) ResolveFunctionName(index)
/*****************************************************************************
/* Local macro definition for retrieving data based on report type
/*****************************************************************************/ #define SELECT_ON_REPORT_TYPE(rt, ival, oval, fval, res) \
{ \ switch ((rt)) { \ case HidP_Input: \ (res) = (ival); \ break; \ \ case HidP_Output: \ (res) = (oval); \ break; \ \ case HidP_Feature: \ (res) = (fval); \ break; \ \ } \ }
/*****************************************************************************
/* Local macro definition for calculating size of a usage value array buffer
/*****************************************************************************/ #define ROUND_TO_NEAREST_BYTE(val) (((val) % 8) ? ((val) / 8) + 1 : ((val) / 8))
/*****************************************************************************
/* Data types local to this module
/*****************************************************************************/
typedef struct _FUNCTION_NAMES { UINT uiIndex; char *szFunctionName; } FUNCTION_NAMES;
typedef struct _PARAMETER_STATE { BOOL fInputReport; BOOL fOutputReport; BOOL fFeatureReport; BOOL fReportID; BOOL fUsagePage; BOOL fUsage; BOOL fLinkCollection; BOOL fInputReportSelect; BOOL fOutputReportSelect; BOOL fFeatureReportSelect; } PARAMETER_STATE;
typedef enum { DLGBOX_INIT_FAILED = -1, DLGBOX_ERROR, DLGBOX_CANCEL, DLGBOX_OK } DLGBOX_STATUS;
typedef struct _ECDISPLAY_PARAMS { HIDP_REPORT_TYPE ReportType; USAGE UsagePage; USAGE Usage; USHORT LinkCollection; UCHAR ReportID; PCHAR szListString; PCHAR szListString2; PUSAGE UsageList; PUSAGE UsageList2; ULONG ListLength; ULONG ListLength2; ULONG Index; union { PHIDP_DATA pDataList; PULONG pValueList; LONG ScaledValue; ULONG Value; }; } ECDISPLAY_PARAMS, *PECDISPLAY_PARAMS;
typedef struct _READ_PARAMS { PHID_DEVICE device; BOOLEAN stopThread; } READ_PARAMS, *PREAD_PARAMS; /*****************************************************************************
/* Local data variables
/*****************************************************************************/
static CHAR szTempBuffer[TEMP_BUFFER_SIZE];
static PBUFFER_DISPLAY pInputDisplay; static PBUFFER_DISPLAY pOutputDisplay; static PBUFFER_DISPLAY pFeatureDisplay;
static FUNCTION_NAMES DeviceCalls[HID_DEVCALLS] = { { HIDD_GET_HID_GUID, "HidD_GetHidGuid" }, { HIDD_GET_FREE_PREPARSED_DATA, "HidD_GetFreePreparsedData" }, { HIDD_GET_CONFIGURATION, "HidD_GetConfiguration" }, { HIDD_SET_CONFIGURATION, "HidD_SetConfiguration" }, { HIDD_FLUSH_QUEUE, "HidD_FlushQueue" }, { HIDD_GET_ATTRIBUTES, "HidD_GetAttributes" }, { HIDD_SET_FEATURE, "HidD_SetFeature" }, { HIDD_GET_FEATURE, "HidD_GetFeature" }, { HIDD_GET_INPUT_REPORT, "HIDD_GetInputReport" }, { HIDD_SET_OUTPUT_REPORT, "HidD_SetOutputReport" }, { HIDD_GET_NUM_INPUT_BUFFERS, "HidD_GetNumInputBuffers" }, { HIDD_SET_NUM_INPUT_BUFFERS, "HidD_SetNumInputBuffers" }, { HIDD_GET_PHYSICAL_DESCRIPTOR, "HidD_GetPhysicalDescriptor" }, { HIDD_GET_MANUFACTURER_STRING, "HidD_GetManufacturerString" }, { HIDD_GET_PRODUCT_STRING, "HidD_GetProductString" }, { HIDD_GET_INDEXED_STRING, "HidD_GetIndexedString" }, { HIDD_GET_SERIAL_NUMBER_STRING, "HidD_GetSerialNumberString" }, { HIDD_GET_MS_GENRE_DESCRIPTOR, "HidD_GetMsGenreDescriptor" }, { HID_READ_REPORT, "Read Input Report" }, { HID_WRITE_REPORT, "Write Report Buffer" }
};
static FUNCTION_NAMES PpdCalls[HID_PPDCALLS] = { { HIDP_GET_BUTTON_CAPS, "HidP_GetButtonCaps" }, { HIDP_GET_BUTTONS, "HidP_GetButtons" }, { HIDP_GET_BUTTONS_EX, "HidP_GetButtonsEx" }, { HIDP_GET_CAPS, "HidP_GetCaps" }, { HIDP_GET_DATA, "HidP_GetData" }, { HIDP_GET_EXTENDED_ATTRIBUTES, "HidP_GetExtendedAttributes" }, { HIDP_GET_LINK_COLL_NODES, "HidP_GetLinkCollectionNodes" }, { HIDP_GET_SCALED_USAGE_VALUE, "HidP_GetScaledUsageValue" }, { HIDP_GET_SPECIFIC_BUTTON_CAPS, "HidP_GetSpecificButtonCaps" }, { HIDP_GET_SPECIFIC_VALUE_CAPS, "HidP_GetSpecificValueCaps" }, { HIDP_GET_USAGES, "HidP_GetUsages" }, { HIDP_GET_USAGES_EX, "HidP_GetUsagesEx" }, { HIDP_GET_USAGE_VALUE, "HidP_GetUsageValue" }, { HIDP_GET_USAGE_VALUE_ARRAY, "HidP_GetUsageValueArray" }, { HIDP_GET_VALUE_CAPS, "HidP_GetValueCaps" }, { HIDP_INITIALIZE_REPORT_FOR_ID, "HidP_InitializeReportForID" }, { HIDP_MAX_DATA_LIST_LENGTH, "HidP_MaxDataListLength" }, { HIDP_MAX_USAGE_LIST_LENGTH, "HidP_MaxUsageListLength" }, { HIDP_SET_BUTTONS, "HidP_SetButtons" }, { HIDP_SET_DATA, "HidP_SetData" }, { HIDP_SET_SCALED_USAGE_VALUE, "HidP_SetScaledUsageValue" }, { HIDP_SET_USAGES, "HidP_SetUsages" }, { HIDP_SET_USAGE_VALUE, "HidP_SetUsageValue" }, { HIDP_SET_USAGE_VALUE_ARRAY, "HidP_SetUsageValueArray" }, { HIDP_TRANSLATE_USAGES, "HidP_TranslateUsagesToI8042ScanCodes" }, { HIDP_UNSET_BUTTONS, "HidP_UnsetButtons" }, { HIDP_UNSET_USAGES, "HidP_UnsetUsages" }, { HIDP_USAGE_LIST_DIFFERENCE, "HidP_UsageListDifference" }, { HID_CLEAR_REPORT, "Clear Report Buffer" } };
static PARAMETER_STATE pState[HID_NUMCALLS] = { { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_HID_GUID
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_FREE_PREPARSED_DATA
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_CONFIGURATION
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_SET_CONFIGURATION
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_FLUSH_QUEUE
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GETATTRIBUTES
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE }, // HIDD_SET_FEATURE
{ FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE }, // HIDD_GET_FEATURE
{ FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE }, // HIDD_GET_INPUT_REPORT
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE }, // HIDD_SET_OUTPUT_REPORT
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_NUM_INPUT_BUFFERS
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_SET_NUM_INPUT_BUFFERS
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_PHYSICAL_DESCRIPTOR
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_MANUFACTURER_STRING
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_PRODUCT_STRING
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_INDEXED_STRING
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_SERIAL_NUMBER_STRING
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDD_GET_MS_GENRE_DESCRIPTOR
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE }, // HID_READ_REPORT
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE }, // HID_WRITE_BUFFER
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_GET_BUTTON_CAPS
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_BUTTONS
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_BUTTONS_EX
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_GET_CAPS
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // HIDP_GET_DATA
{ TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // HIDP_GET_EXTENDED_ATTRIBUTES
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_GET_LINK_COLL_NODES
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_SCALED_USAGE_VALUE
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE }, // HIDP_GET_SPECIFIC_BUTTON_CAPS
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE }, // HIDP_GET_SPECIFIC_VALUE_CAPS
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_USAGES
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_USAGES_EX
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_USAGE_VALUE
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // HIDP_GET_USAGE_VALUE_ARRAY
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_GET_VALUE_CAPS
{ TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // HIDP_INITIALIZE_REPORT_FOR_ID
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_MAX_DATA_LIST_LENGTH
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_MAX_USAGE_LIST_LENGTH
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_SET_BUTTONS
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }, // HIDP_SET_DATA
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // HIDP_SET_SCALED_USAGE_VALUE
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_SET_USAGES
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // HIDP_SET_USAGE_VALUE
{ TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE }, // HIDP_SET_USAGE_VALUE_ARRAY
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_TRANSLATE_USAGES
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_UNSET_BUTTONS
{ TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE }, // HIDP_UNSET_USAGES
{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // HIDP_USAGE_LIST_DIFFERENCE
{ TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE } // HID_CLEAR_BUFFER
};
/*****************************************************************************
/* Local function declarations
/*****************************************************************************/
VOID vLoadExtCalls( HWND hExtCalls );
VOID vSetReportType( HWND hDlg, LONG lId );
VOID vInitEditText( HWND hText, INT cbTextSize, CHAR *pchText );
VOID vEnableParameters( HWND hDlg, LRESULT iCallSelection );
BOOL fGetAndVerifyParameters( HWND hDlg, PECDISPLAY_PARAMS pParams );
BOOL ECDisp_Execute( IN INT FuncCall, IN OUT PEXTCALL_PARAMS CallParams, OUT PEXTCALL_STATUS CallStatus );
VOID ECDisp_DisplayOutput( IN HWND hOutputWindow, IN INT FuncCall, IN PEXTCALL_PARAMS Results );
VOID vExecuteAndDisplayOutput( HWND hOutputWindow, PHID_DEVICE pDevice, INT iFuncCall, PECDISPLAY_PARAMS pParams );
CHAR *pchGetHidAppStatusString( NTSTATUS StatusCode );
VOID vInitECControls( HWND hDlg, USHORT InputReportByteLength, PBUFFER_DISPLAY *ppInputDisplay, USHORT OutputReportByteLength, PBUFFER_DISPLAY *ppOutputDisplay, USHORT FeatureReportByteLength, PBUFFER_DISPLAY *ppFeatureDisplay );
VOID BuildReportIDList( IN PHIDP_BUTTON_CAPS phidButtonCaps, IN USHORT nButtonCaps, IN PHIDP_VALUE_CAPS phidValueCaps, IN USHORT nValueCaps, OUT UCHAR **ppReportIDList, OUT INT *nReportIDs );
LRESULT CALLBACK bSetUsagesDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bSetValueDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bSetInputBuffDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bSetDataDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bSetBufLenDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bSetInputBuffersDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bGetIndexedDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK bGetUsageDiffDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
BOOL ConvertStringToUnsignedList( IN INT iUnsignedSize, IN INT iBase, IN OUT PCHAR InString, OUT PCHAR *UnsignedList, OUT PULONG nUnsigneds );
BOOL ConvertStringToUlongList( IN OUT PCHAR InString, OUT PULONG *UlongList, OUT PULONG nUlongs );
BOOL ConvertStringToUsageList( IN OUT PCHAR InString, OUT PUSAGE *UsageList, OUT PULONG nUsages );
VOID ECDisp_MakeGUIDString( IN GUID guid, OUT CHAR szString[], IN UINT uiBuffSize );
PCHAR ECDisp_GetHidAppStatusString( NTSTATUS StatusCode );
BOOL ECDisp_ConvertUlongListToValueList( IN PULONG UlongList, IN ULONG nUlongs, IN USHORT BitSize, IN USHORT ReportCount, OUT PCHAR *ValueList, OUT PULONG ValueListSize );
BOOL SetDlgItemIntHex( HWND hDlg, INT nIDDlgItem, UINT uValue, INT nBytes );
PCHAR ResolveFunctionName( INT Index );
DWORD WINAPI ECDisp_ReadThreadProc( LPVOID ThreadContext );
VOID DisplayExtendedAttributes( IN HWND OutputWindow, IN PHIDP_UNKNOWN_TOKEN UnknownList, IN ULONG UnknownListLength );
/*****************************************************************************
/* Global function definitions
/*****************************************************************************/
LRESULT CALLBACK bExtCallDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PHID_DEVICE pDevice; static CHAR szTempBuff[1024]; static CHAR szLabel[512]; static CHAR szValue[512]; static INT iLBCounter; static UCHAR *pucInputReportIDs; static UCHAR *pucOutputReportIDs; static UCHAR *pucFeatureReportIDs; static INT nInputReportIDs; static INT nOutputReportIDs; static INT nFeatureReportIDs; static HANDLE ReadThread; static READ_THREAD_CONTEXT readContext; INT iIndex; ECDISPLAY_PARAMS params; DWORD threadID;
switch(message) { case WM_INITDIALOG: /*
// Initializing the dialog box involves the following steps:
// 1) Determine from the parameter the pointer to the selected device
// 2) Initializing the controls in the dialog box to their initial values
// 3) Send a message that our list of routines has changed
*/ pDevice = (PHID_DEVICE) lParam;
vInitECControls(hDlg, pDevice -> Caps.InputReportByteLength, &pInputDisplay, pDevice -> Caps.OutputReportByteLength, &pOutputDisplay, pDevice -> Caps.FeatureReportByteLength, &pFeatureDisplay);
ReadThread = NULL; PostMessage(hDlg, WM_COMMAND, IDC_EXTCALLS + (CBN_SELCHANGE << 16), (LPARAM) GetDlgItem(hDlg,IDC_EXTCALLS)); break;
case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_EXTCALLS: switch (HIWORD(wParam)) { case CBN_SELCHANGE: iIndex = (INT) SendDlgItemMessage(hDlg, IDC_EXTCALLS, CB_GETCURSEL, 0, 0); vEnableParameters(hDlg, SendDlgItemMessage(hDlg, IDC_EXTCALLS, CB_GETITEMDATA, iIndex, 0)); break; } break;
case IDC_INPUT_SELECT: if (CBN_SELCHANGE == HIWORD(wParam)) { BufferDisplay_ChangeSelection(pInputDisplay); } break;
case IDC_OUTPUT_SELECT: if (CBN_SELCHANGE == HIWORD(wParam)) { BufferDisplay_ChangeSelection(pOutputDisplay); } break;
case IDC_FEATURE_SELECT: if (CBN_SELCHANGE == HIWORD(wParam)) { BufferDisplay_ChangeSelection(pFeatureDisplay); } break; case IDC_EXECUTE: /*
// Get the parameters and verify that they are all correct
// If there is an error, display an error message and
// don't continue any further.
*/
if ( !fGetAndVerifyParameters(hDlg, ¶ms) ) { ECDISP_ERROR(hDlg, "Error: One or more parameters are invalid"); }
/*
// Else the parameters are valid and we can execute the call
*/ else { iIndex = (INT) SendDlgItemMessage(hDlg, IDC_EXTCALLS, CB_GETCURSEL, 0, 0); iIndex = (INT) SendDlgItemMessage(hDlg, IDC_EXTCALLS, CB_GETITEMDATA, iIndex, 0);
/*
// Now that we know the function to execute we need to execute it
// and output the data
*/
SendDlgItemMessage(hDlg, IDC_CALLOUTPUT, LB_RESETCONTENT, 0, 0); vExecuteAndDisplayOutput(GetDlgItem(hDlg, IDC_CALLOUTPUT), pDevice, iIndex, ¶ms); } break; /* end IDC_EXECUTE case */
/*
// Start up a read thread that can read input reports while
// we operate on the other stuff
*/ case IDC_READ_SYNCH: case IDC_READ_ASYNCH: if (NULL == ReadThread) { readContext.HidDevice = pDevice; readContext.TerminateThread = FALSE; readContext.DoOneRead = TRUE; readContext.DisplayEvent = NULL; readContext.DisplayWindow = hDlg;
ReadThread = CreateThread( NULL, 0, (LOWORD(wParam) == IDC_READ_SYNCH) ? SynchReadThreadProc : AsynchReadThreadProc, (LPVOID) &readContext, 0, &threadID);
if (NULL == ReadThread) { MessageBox(hDlg, "Unable to create read thread", HCLIENT_ERROR, MB_ICONEXCLAMATION); } else { EnableWindow(GetDlgItem(hDlg, IDC_READ_SYNCH), (LOWORD(wParam) == IDC_READ_SYNCH));
EnableWindow(GetDlgItem(hDlg, IDC_READ_ASYNCH), (LOWORD(wParam) == IDC_READ_ASYNCH));
SetWindowText(GetDlgItem(hDlg, LOWORD(wParam)), "Stop Read Thread"); EnableWindow(GetDlgItem(hDlg, IDC_CANCEL), FALSE); } } else { readContext.TerminateThread = TRUE;
WaitForSingleObject(ReadThread, INFINITE);
ReadThread = NULL; SetWindowText(GetDlgItem(hDlg, IDC_READ_SYNCH), "Start Synchronous Read Thread");
SetWindowText(GetDlgItem(hDlg, IDC_READ_ASYNCH), "Start Asynchronous Read Thread");
EnableWindow(GetDlgItem(hDlg, IDC_READ_SYNCH), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_READ_ASYNCH), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_CANCEL), TRUE); } break;
case IDC_CANCEL: BufferDisplay_Destroy(pInputDisplay); BufferDisplay_Destroy(pOutputDisplay); BufferDisplay_Destroy(pFeatureDisplay); EndDialog(hDlg, 0); break; } break;
case WM_CLOSE: PostMessage(hDlg, WM_COMMAND, IDC_CANCEL, 0); break;
} return FALSE; }
VOID vLoadExtCalls( HWND hExtCalls ) { INT iIndex; UINT uiIndex;
/*
// Load the physical device specific calls
*/ for (uiIndex = 0; uiIndex < HID_DEVCALLS; uiIndex++) { iIndex = (INT) SendMessage(hExtCalls, CB_ADDSTRING, 0, (LPARAM) DeviceCalls[uiIndex].szFunctionName);
if (CB_ERR != iIndex && CB_ERRSPACE != iIndex) { SendMessage(hExtCalls, CB_SETITEMDATA, iIndex, DeviceCalls[uiIndex].uiIndex); } }
/*
// Load the other device calls no matter what
*/
for (uiIndex = 0; uiIndex < HID_PPDCALLS; uiIndex++) { iIndex = (INT) SendMessage(hExtCalls, CB_ADDSTRING, 0, (LPARAM) PpdCalls[uiIndex].szFunctionName);
if (CB_ERR != iIndex && CB_ERRSPACE != iIndex) { SendMessage(hExtCalls, CB_SETITEMDATA, iIndex, PpdCalls[uiIndex].uiIndex); } } SendMessage(hExtCalls, CB_SETCURSEL, 0, 0);
return; }
VOID vSetReportType( HWND hDlg, LONG lId ) { CheckRadioButton(hDlg, IDC_INPUT, IDC_FEATURE, lId); return; }
VOID vInitEditText( HWND hText, INT cbTextSize, CHAR *pchText ) { SendMessage(hText, EM_SETLIMITTEXT, (WPARAM) cbTextSize, 0); SendMessage(hText, EM_REPLACESEL, 0, (LPARAM) pchText);
return; }
VOID vEnableParameters( HWND hDlg, LRESULT iCallSelection ) { EnableWindow(GetDlgItem(hDlg, IDC_INPUT), pState[iCallSelection-1].fInputReport); EnableWindow(GetDlgItem(hDlg, IDC_OUTPUT), pState[iCallSelection-1].fOutputReport); EnableWindow(GetDlgItem(hDlg, IDC_FEATURE), pState[iCallSelection-1].fFeatureReport); EnableWindow(GetDlgItem(hDlg, IDC_REPORTID), pState[iCallSelection-1].fReportID); EnableWindow(GetDlgItem(hDlg, IDC_USAGEPAGE), pState[iCallSelection-1].fUsagePage); EnableWindow(GetDlgItem(hDlg, IDC_USAGE), pState[iCallSelection-1].fUsage); EnableWindow(GetDlgItem(hDlg, IDC_LINKCOLL), pState[iCallSelection-1].fLinkCollection); EnableWindow(GetDlgItem(hDlg, IDC_INPUT_SELECT), pState[iCallSelection-1].fInputReportSelect); EnableWindow(GetDlgItem(hDlg, IDC_OUTPUT_SELECT), pState[iCallSelection-1].fOutputReportSelect); EnableWindow(GetDlgItem(hDlg, IDC_FEATURE_SELECT), pState[iCallSelection-1].fFeatureReportSelect);
return; } BOOL fGetAndVerifyParameters( HWND hDlg, PECDISPLAY_PARAMS pParams ) { /*
// Declare a text buffer of size 7 since the parameter limit is at most 6
// characters in the edit box.
*/ CHAR WindowText[7]; BOOL fStatus = TRUE; PCHAR nptr; if (IsDlgButtonChecked(hDlg, IDC_INPUT)) { pParams -> ReportType = HidP_Input; } else if (IsDlgButtonChecked(hDlg, IDC_OUTPUT)) { pParams -> ReportType = HidP_Output; } else { pParams -> ReportType = HidP_Feature; }
/*
// Get and verify the usage page window text;
*/ GetWindowText(GetDlgItem(hDlg, IDC_USAGEPAGE), WindowText, 7);
pParams -> UsagePage = (USAGE) strtol(WindowText, &nptr, 16);
if (*nptr != '\0') { fStatus = FALSE; pParams -> UsagePage = 0; }
/*
// Get and verify the usage window text
*/
GetWindowText(GetDlgItem(hDlg, IDC_USAGE), WindowText, 7);
pParams -> Usage = (USAGE) strtol(WindowText, &nptr, 16);
if (*nptr != '\0') { fStatus = FALSE; pParams -> Usage = 0; } /*
// Get and verify the link collection window text
*/
GetWindowText(GetDlgItem(hDlg, IDC_LINKCOLL), WindowText, 7);
pParams -> LinkCollection = (USAGE) strtol(WindowText, &nptr, 16);
if (*nptr != '\0') { fStatus = FALSE; pParams -> LinkCollection = 0; } GetWindowText(GetDlgItem(hDlg, IDC_REPORTID), WindowText, 7);
pParams -> ReportID = (UCHAR) strtol(WindowText, &nptr, 10); if (*nptr != '\0') { fStatus = FALSE; pParams -> ReportID = 0; }
return (fStatus); }
VOID vInitECControls( HWND hDlg, USHORT InputReportByteLength, PBUFFER_DISPLAY *ppInputDisplay, USHORT OutputReportByteLength, PBUFFER_DISPLAY *ppOutputDisplay, USHORT FeatureReportByteLength, PBUFFER_DISPLAY *ppFeatureDisplay ) { BOOLEAN fInitStatus;
/*
// Begin by initializing the combo box with the calls that can be executed
*/
vLoadExtCalls(GetDlgItem(hDlg, IDC_EXTCALLS));
/*
// Set the radio buttons initially to the input report type
*/ vSetReportType(hDlg, IDC_INPUT); /*
// Initialize the edit controls text
*/
vInitEditText(GetDlgItem(hDlg, IDC_USAGEPAGE), 6, "0x0000"); vInitEditText(GetDlgItem(hDlg, IDC_USAGE), 6, "0x0000"); vInitEditText(GetDlgItem(hDlg, IDC_LINKCOLL), 2, "0"); vInitEditText(GetDlgItem(hDlg, IDC_REPORTID), 3, "0");
/*
// Initialize the report buffer boxes
*/
fInitStatus = BufferDisplay_Init(GetDlgItem(hDlg, IDC_INPUT_SELECT), GetDlgItem(hDlg, IDC_INPUT_BUFFER), NUM_INPUT_BUFFERS, InputReportByteLength, HidP_Input, ppInputDisplay);
if (!fInitStatus) { ECDISP_ERROR(hDlg, "Error initializing input buffer display"); }
fInitStatus = BufferDisplay_Init(GetDlgItem(hDlg, IDC_OUTPUT_SELECT), GetDlgItem(hDlg, IDC_OUTPUT_BUFFER), NUM_OUTPUT_BUFFERS, OutputReportByteLength, HidP_Output, ppOutputDisplay);
if (!fInitStatus) { ECDISP_ERROR(hDlg, "Error initializing output buffer display"); }
fInitStatus = BufferDisplay_Init(GetDlgItem(hDlg, IDC_FEATURE_SELECT), GetDlgItem(hDlg, IDC_FEATURE_BUFFER), NUM_FEATURE_BUFFERS, FeatureReportByteLength, HidP_Feature, ppFeatureDisplay);
if (!fInitStatus) { ECDISP_ERROR(hDlg, "Error initializing feature buffer display"); }
/*
// Reset the output box content
*/ SendMessage(GetDlgItem(hDlg, IDC_CALLOUTPUT), LB_RESETCONTENT, 0, 0); return; } BOOL ECDisp_Execute( IN INT FuncCall, IN OUT PEXTCALL_PARAMS CallParams, OUT PEXTCALL_STATUS CallStatus ) /*++
RoutineDescription: This routine is a complex routine for executing all of the functions. The routine was originally developed with consideration for future use that never materialized.
It makes use of the calls in extcalls.c which basically execute the given function and does some verification on the buffers that are passed down to HID.DLL.
The input parameters are specify the function call to execute, the call parameters structures and the call status structure.
If any further buffers are needed for the specific calls, they will be allocated here.
The CallStatus parameters is a structure set by the ExtCalls_ routines
Future versions of the HClient sample may remove this routine and/or the ExtCalls_ routines to simply the code. --*/ { BOOL ExecuteStatus; HIDP_VALUE_CAPS ValueCaps; USHORT ValueCapsLength; PULONG ValueList;
NTSTATUS status; DWORD numBytes; ULONG size;
/*
// Initially assume everything will go correctly and will set otherwise
// depending on the function call.
*/
CallStatus -> IsHidError = FALSE;
switch (FuncCall) { case HID_READ_REPORT: CallStatus -> IsHidError = !ReadFile(CallParams -> DeviceHandle, CallParams -> ReportBuffer, CallParams -> ReportLength, &numBytes, NULL); return (TRUE); break;
case HID_WRITE_REPORT: CallStatus -> IsHidError = !WriteFile(CallParams -> DeviceHandle, CallParams -> ReportBuffer, CallParams -> ReportLength, &numBytes, NULL); return (TRUE); break;
case HIDD_FLUSH_QUEUE: CallStatus -> IsHidError = !HidD_FlushQueue(CallParams -> DeviceHandle); return (TRUE); break;
case HIDD_GET_HID_GUID: CallParams -> List = malloc(sizeof(GUID));
if (NULL != CallParams -> List) { HidD_GetHidGuid((GUID *) CallParams -> List); } return (NULL != CallParams -> List); break;
case HIDD_GET_PREPARSED_DATA: CallStatus -> IsHidError = !HidD_GetPreparsedData(CallParams -> DeviceHandle, CallParams -> ppPd); return (TRUE);
case HIDD_FREE_PREPARSED_DATA: CallStatus -> IsHidError = !HidD_FreePreparsedData(CallParams -> Ppd); return (TRUE);
case HIDD_GET_ATTRIBUTES: CallParams -> List = malloc(sizeof(HIDD_ATTRIBUTES));
if (NULL != CallParams -> List) { CallStatus -> IsHidError = !HidD_GetAttributes(CallParams -> DeviceHandle, CallParams -> List); } return (NULL != CallParams -> List); case HIDD_GET_FEATURE: *(CallParams -> ReportBuffer) = CallParams -> ReportID;
CallStatus -> IsHidError = !HidD_GetFeature(CallParams -> DeviceHandle, CallParams -> ReportBuffer, CallParams -> ReportLength); return (TRUE);
case HIDD_SET_FEATURE: CallStatus -> IsHidError = !HidD_SetFeature(CallParams -> DeviceHandle, CallParams -> ReportBuffer, CallParams -> ReportLength); return (TRUE);
case HIDD_GET_INPUT_REPORT: *(CallParams -> ReportBuffer) = CallParams -> ReportID;
CallStatus -> IsHidError = !HidD_GetInputReport(CallParams -> DeviceHandle, CallParams -> ReportBuffer, CallParams -> ReportLength); return (TRUE);
case HIDD_SET_OUTPUT_REPORT: CallStatus -> IsHidError = !HidD_SetOutputReport(CallParams -> DeviceHandle, CallParams -> ReportBuffer, CallParams -> ReportLength); return (TRUE);
case HIDD_GET_NUM_INPUT_BUFFERS: CallStatus -> IsHidError = !HidD_GetNumInputBuffers(CallParams -> DeviceHandle, &CallParams -> Value); return (TRUE);
case HIDD_SET_NUM_INPUT_BUFFERS: CallStatus -> IsHidError = !HidD_SetNumInputBuffers(CallParams -> DeviceHandle, CallParams -> Value);
return (TRUE);
case HIDD_GET_PHYSICAL_DESCRIPTOR: CallParams -> List = (PCHAR) malloc (CallParams -> ListLength);
if (NULL != CallParams -> List ) { CallStatus -> IsHidError = !HidD_GetPhysicalDescriptor(CallParams -> DeviceHandle, CallParams -> List, CallParams -> ListLength); } return (NULL != CallParams -> List);
case HIDD_GET_MANUFACTURER_STRING: CallParams -> List = (PWCHAR) malloc (CallParams -> ListLength);
if (NULL != CallParams -> List ) { CallStatus -> IsHidError = !HidD_GetManufacturerString(CallParams -> DeviceHandle, CallParams -> List, CallParams -> ListLength); } return (NULL != CallParams -> List);
case HIDD_GET_PRODUCT_STRING: CallParams -> List = (PWCHAR) malloc (CallParams -> ListLength);
if (NULL != CallParams -> List ) { CallStatus -> IsHidError = !HidD_GetProductString(CallParams -> DeviceHandle, CallParams -> List, CallParams -> ListLength); } return (NULL != CallParams -> List);
case HIDP_GET_EXTENDED_ATTRIBUTES: CallParams -> List = (PWCHAR) malloc (CallParams -> ListLength); if (NULL != CallParams -> List ) { status = pfnHidP_GetExtendedAttributes(CallParams -> ReportType, (USHORT) CallParams -> Index, CallParams -> Ppd, CallParams -> List, &CallParams -> ListLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List); case HIDD_GET_INDEXED_STRING: CallParams -> List = (PWCHAR) malloc (CallParams -> ListLength);
if (NULL != CallParams -> List ) { CallStatus -> IsHidError = !HidD_GetIndexedString(CallParams -> DeviceHandle, CallParams -> Index, CallParams -> List, CallParams -> ListLength); } return (NULL != CallParams -> List); case HIDD_GET_SERIAL_NUMBER_STRING: CallParams -> List = (PWCHAR) malloc (CallParams -> ListLength);
if (NULL != CallParams -> List ) { CallStatus -> IsHidError = !HidD_GetSerialNumberString(CallParams -> DeviceHandle, CallParams -> List, CallParams -> ListLength); } return (NULL != CallParams -> List);
case HIDD_GET_MS_GENRE_DESCRIPTOR: CallParams -> List = (PCHAR) malloc (CallParams -> ListLength);
if (NULL != CallParams -> List ) { CallStatus -> IsHidError = !HidD_GetMsGenreDescriptor(CallParams -> DeviceHandle, CallParams -> List, CallParams -> ListLength); } return (NULL != CallParams -> List);
case HIDP_GET_BUTTON_CAPS: size = CallParams -> ListLength * sizeof(HIDP_BUTTON_CAPS);
CallParams -> List = malloc(size);
if (NULL != CallParams -> List) { status = HidP_GetButtonCaps(CallParams -> ReportType, CallParams -> List, (PUSHORT) &CallParams -> ListLength, CallParams -> Ppd);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_BUTTONS:
CallParams -> ListLength = HidP_MaxUsageListLength(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> Ppd);
CallParams -> List = malloc(CallParams -> ListLength * sizeof(USAGE));
if (NULL != CallParams -> List) { status = HidP_GetButtons(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_BUTTONS_EX:
CallParams -> ListLength = HidP_MaxUsageListLength(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> Ppd);
CallParams -> List = malloc(CallParams -> ListLength * sizeof(USAGE_AND_PAGE));
if (NULL != CallParams -> List) { status = HidP_GetButtonsEx(CallParams -> ReportType, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_CAPS:
CallParams -> ListLength = sizeof(HIDP_CAPS);
CallParams -> List = malloc(sizeof(HIDP_CAPS));
if (NULL != CallParams -> List) { status = HidP_GetCaps(CallParams -> Ppd, CallParams -> List);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_DATA:
CallParams -> ListLength = HidP_MaxDataListLength(CallParams -> ReportType, CallParams -> Ppd);
CallParams -> List = malloc(CallParams -> ListLength * sizeof(HIDP_DATA));
if (NULL != CallParams -> List) { status = HidP_GetData(CallParams -> ReportType, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_LINK_COLL_NODES: CallParams -> List = malloc(CallParams -> ListLength * sizeof(HIDP_LINK_COLLECTION_NODE));
if (NULL != CallParams -> List) { status = HidP_GetLinkCollectionNodes(CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_SCALED_USAGE_VALUE:
status = HidP_GetScaledUsageValue(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, &CallParams -> ScaledValue, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_GET_SPECIFIC_BUTTON_CAPS:
CallParams -> List = malloc(CallParams -> ListLength * sizeof(HIDP_BUTTON_CAPS));
if (NULL != CallParams -> List) { status = HidP_GetSpecificButtonCaps(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, CallParams -> List, (PUSHORT) &CallParams -> ListLength, CallParams -> Ppd);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List); case HIDP_GET_SPECIFIC_VALUE_CAPS:
CallParams -> List = malloc(CallParams -> ListLength * sizeof(HIDP_VALUE_CAPS));
if (NULL != CallParams -> List) { status = HidP_GetSpecificValueCaps(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, CallParams -> List, (PUSHORT) &CallParams -> ListLength, CallParams -> Ppd);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_USAGES: CallParams -> ListLength = HidP_MaxUsageListLength(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> Ppd);
CallParams -> List = malloc(CallParams -> ListLength * sizeof(USAGE));
if (NULL != CallParams -> List) { status = HidP_GetUsages(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_USAGES_EX: CallParams -> ListLength = HidP_MaxUsageListLength(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> Ppd);
CallParams -> List = malloc(CallParams -> ListLength * sizeof(USAGE_AND_PAGE));
if (NULL != CallParams -> List) { status = HidP_GetUsagesEx(CallParams -> ReportType, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List); case HIDP_GET_USAGE_VALUE: status = HidP_GetUsageValue(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, &CallParams -> Value, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_GET_USAGE_VALUE_ARRAY:
ValueCapsLength = 1; status = HidP_GetSpecificValueCaps(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, &ValueCaps, &ValueCapsLength, CallParams -> Ppd);
if (HIDP_STATUS_SUCCESS != status) { return (FALSE); }
CallParams -> BitSize = ValueCaps.BitSize; CallParams -> ReportCount = ValueCaps.ReportCount; CallParams -> ListLength = ROUND_TO_NEAREST_BYTE(CallParams -> BitSize * CallParams -> ReportCount);
CallParams -> List = malloc(CallParams -> ListLength);
if (NULL != CallParams -> List) { status = HidP_GetUsageValueArray(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, CallParams -> List, (USHORT) CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; } return (NULL != CallParams -> List);
case HIDP_GET_VALUE_CAPS: CallParams -> List = malloc(CallParams -> ListLength * sizeof(HIDP_VALUE_CAPS)); if (NULL != CallParams -> List) { status = HidP_GetValueCaps(CallParams -> ReportType, CallParams -> List, (PUSHORT) &CallParams -> ListLength, CallParams -> Ppd);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; }
case HIDP_INITIALIZE_REPORT_FOR_ID: status = pfnHidP_InitializeReportForID(CallParams -> ReportType, CallParams -> ReportID, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_MAX_USAGE_LIST_LENGTH:
CallParams -> Value = HidP_MaxUsageListLength(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> Ppd);
CallStatus -> IsHidError = FALSE; CallStatus -> HidErrorCode = HIDP_STATUS_SUCCESS;
return (TRUE);
case HIDP_MAX_DATA_LIST_LENGTH:
CallParams -> Value = HidP_MaxDataListLength(CallParams -> ReportType, CallParams -> Ppd);
CallStatus -> IsHidError = FALSE; CallStatus -> HidErrorCode = HIDP_STATUS_SUCCESS;
return (TRUE);
case HIDP_SET_BUTTONS:
status = HidP_SetButtons(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_SET_DATA:
status = HidP_SetData(CallParams -> ReportType, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_SET_SCALED_USAGE_VALUE: status = HidP_SetUsageValue(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, CallParams -> ScaledValue, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_SET_USAGES: status = HidP_SetUsages(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_SET_USAGE_VALUE: status = HidP_SetUsageValue(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, CallParams -> Value, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_SET_USAGE_VALUE_ARRAY:
ValueCapsLength = 1; status = HidP_GetSpecificValueCaps(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, &ValueCaps, &ValueCapsLength, CallParams -> Ppd);
if (HIDP_STATUS_SUCCESS != status) { return (FALSE); } CallParams -> BitSize = ValueCaps.BitSize; CallParams -> ReportCount = ValueCaps.ReportCount;
ValueList = CallParams -> List; ExecuteStatus = ECDisp_ConvertUlongListToValueList(ValueList, CallParams -> ListLength, CallParams -> BitSize, CallParams -> ReportCount, (PCHAR *) &CallParams -> List, &CallParams -> ListLength);
if (!ExecuteStatus) { return (FALSE); }
status = HidP_SetUsageValueArray(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> Usage, CallParams -> List, (USHORT) CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_UNSET_BUTTONS: status = HidP_UnsetButtons(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE);
case HIDP_UNSET_USAGES: status = HidP_UnsetUsages(CallParams -> ReportType, CallParams -> UsagePage, CallParams -> LinkCollection, CallParams -> List, &CallParams -> ListLength, CallParams -> Ppd, CallParams -> ReportBuffer, CallParams -> ReportLength); CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status; return (TRUE);
case HIDP_USAGE_LIST_DIFFERENCE: CallParams -> MakeList = (PUSAGE) malloc (sizeof(USAGE) * CallParams -> ListLength);
if (NULL == CallParams -> MakeList) { return (FALSE); }
CallParams -> BreakList = (PUSAGE) malloc (sizeof(USAGE) * CallParams -> ListLength); if (NULL == CallParams -> BreakList) { free(CallParams -> MakeList);
return (FALSE); }
status = HidP_UsageListDifference(CallParams -> List, CallParams -> List2, CallParams -> BreakList, CallParams -> MakeList, CallParams -> ListLength);
CallStatus -> IsHidError = (HIDP_STATUS_SUCCESS != status); CallStatus -> HidErrorCode = status;
return (TRUE); } return (FALSE); }
VOID ECDisp_DisplayOutput( IN HWND hOutputWindow, IN INT FuncCall, IN PEXTCALL_PARAMS Results ) /*++
RoutineDescription: This routine is responsible for displaying the output from calls to HID.DLL functions. It must extract and interpret the appropriate data from the PEXTCALL_PARAMS structure. --*/ { PHIDP_LINK_COLLECTION_NODE NodeList; PHIDP_BUTTON_CAPS ButtonCaps; PHIDP_VALUE_CAPS ValueCaps; PHIDP_DATA DataList; PHIDP_EXTENDED_ATTRIBUTES ExtAttrib; PUSAGE_AND_PAGE UsageAndPageList; PUSAGE UsageList; PCHAR UsageValueArray; PBUFFER_DISPLAY pDisplay; PCHAR PhysDescString; PCHAR GenreDescString; SIZE_T StringLength; UINT RemainingBuffer=0;
ULONG Index; HRESULT stringReturn;
switch (FuncCall) { case HIDD_GET_HID_GUID:
stringReturn = StringCbCopy(szTempBuffer, TEMP_BUFFER_SIZE, "HID Guid: "); StringLength = strlen(szTempBuffer); if (StringLength < TEMP_BUFFER_SIZE) { RemainingBuffer = (UINT)(TEMP_BUFFER_SIZE - StringLength); } ECDisp_MakeGUIDString(*((LPGUID) Results -> List), &szTempBuffer[StringLength], RemainingBuffer);
OUTSTRING(hOutputWindow, szTempBuffer); break;
case HIDD_GET_ATTRIBUTES: vDisplayDeviceAttributes((PHIDD_ATTRIBUTES) Results -> List, hOutputWindow); break;
case HIDD_GET_NUM_INPUT_BUFFERS: stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "Number input buffers: %u", Results -> Value);
OUTSTRING(hOutputWindow, szTempBuffer); break;
case HIDD_GET_MS_GENRE_DESCRIPTOR: OUTSTRING(hOutputWindow, "MS Genre Descriptor"); OUTSTRING(hOutputWindow, "==================="); /*
// To display a physical descriptor, the procedure currently just
// creates a string data buffer by bytes and displays that
// in the results box. It will display in rows of 16 bytes apiece.
*/ Index = 0; while (Index < Results -> ListLength) { Strings_CreateDataBufferString(((PCHAR) Results -> List) + Index, Results -> ListLength - Index, 16, 1, &GenreDescString);
if (NULL != GenreDescString) { OUTSTRING(hOutputWindow, GenreDescString); free(GenreDescString); } else { OUTSTRING(hOutputWindow, "Error trying to display ms genre descriptor"); } Index += 16; } break;
case HIDD_GET_PHYSICAL_DESCRIPTOR: OUTSTRING(hOutputWindow, "Physical Descriptor"); OUTSTRING(hOutputWindow, "===================");
/*
// To display a physical descriptor, the procedure currently just
// creates a string data buffer by bytes and displays that
// in the results box. It will display in rows of 16 bytes apiece.
*/ Index = 0; while (Index < Results -> ListLength) { Strings_CreateDataBufferString(((PCHAR) Results -> List) + Index, Results -> ListLength - Index, 16, 1, &PhysDescString);
if (NULL != PhysDescString) { OUTSTRING(hOutputWindow, PhysDescString); free(PhysDescString); } else { OUTSTRING(hOutputWindow, "Error trying to display physical descriptor"); } Index += 16; } break;
/*
// For the string descriptor call routines, the returned string is stored
// in the Results -> List parameter. It should be noted that the
// strings returned by these calls are wide-char strings and that these
// string are terminated with a NULL character if there was space withing
// the buffer to add such a character. If the buffer was only big enough
// to hold the characters of the string, there will be no null terminator
// and the output string display mechanism may fail to properly display this
// type of string. Fixing of this display mechanism is a future (low priority)
// workitem.
*/ case HIDD_GET_PRODUCT_STRING: OUTSTRING(hOutputWindow, "Product String"); OUTSTRING(hOutputWindow, "=============="); OUTWSTRING(hOutputWindow, Results -> List); break;
case HIDD_GET_MANUFACTURER_STRING: OUTSTRING(hOutputWindow, "Manufacturer String"); OUTSTRING(hOutputWindow, "==================="); OUTWSTRING(hOutputWindow, Results -> List); break;
case HIDD_GET_INDEXED_STRING: stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "Indexed String #%u:", Results -> Index);
OUTSTRING(hOutputWindow, szTempBuffer); OUTSTRING(hOutputWindow, "==================="); OUTWSTRING(hOutputWindow, Results -> List); break;
case HIDD_GET_SERIAL_NUMBER_STRING: OUTSTRING(hOutputWindow, "Serial Number String"); OUTSTRING(hOutputWindow, "====================="); OUTWSTRING(hOutputWindow, Results -> List); break; case HIDP_GET_BUTTON_CAPS: case HIDP_GET_SPECIFIC_BUTTON_CAPS:
ButtonCaps = (PHIDP_BUTTON_CAPS) (Results -> List); for (Index = 0; Index < Results -> ListLength; Index++, ButtonCaps++) { OUTSTRING(hOutputWindow, "=========================="); vDisplayButtonAttributes(ButtonCaps, hOutputWindow); } break;
/*
// HidP_GetButtons and HidP_GetUsages are in reality the same call.
// HidP_GetButtons actually a macro which gets redefined into
// HidP_GetUsages with the same parameter order. That is why their
// display mechanisms are identical. This call returns in the
// List parameter a list of Usages. The display mechanism converts
// these usages into a string of numbers.
*/ case HIDP_GET_BUTTONS: case HIDP_GET_USAGES:
OUTSTRING(hOutputWindow, "Usages Returned"); OUTSTRING(hOutputWindow, "===============");
UsageList = (PUSAGE) Results -> List; for (Index = 0; Index < Results -> ListLength; Index++) { vCreateUsageString(UsageList + Index, szTempBuffer);
OUTSTRING(hOutputWindow, szTempBuffer); } break;
/*
// Like get their siblings, the normal get functions, these routines are
// currently one in the same. The difference between these routines
// and their siblings is the return of a usage page along with each
// usage. Therefore, both values must be displayed at the same time.
*/ case HIDP_GET_BUTTONS_EX: case HIDP_GET_USAGES_EX:
OUTSTRING(hOutputWindow, "Usages Returned"); OUTSTRING(hOutputWindow, "===============");
UsageAndPageList = (PUSAGE_AND_PAGE) Results -> List; for (Index = 0; Index < Results -> ListLength; Index++) { vCreateUsageAndPageString(UsageAndPageList + Index, szTempBuffer);
OUTSTRING(hOutputWindow, szTempBuffer); } break;
case HIDP_GET_CAPS: vDisplayDeviceCaps((PHIDP_CAPS) Results -> List, hOutputWindow); break;
case HIDP_GET_DATA: OUTSTRING(hOutputWindow, "Data Indices"); OUTSTRING(hOutputWindow, "============"); DataList = (PHIDP_DATA) Results -> List; for (Index = 0; Index < Results -> ListLength; Index++) { vDisplayDataAttributes(DataList+Index, FALSE, hOutputWindow); } break;
case HIDP_GET_EXTENDED_ATTRIBUTES: OUTSTRING(hOutputWindow, "Extended Attributes"); OUTSTRING(hOutputWindow, "==================="); ExtAttrib = (PHIDP_EXTENDED_ATTRIBUTES) Results -> List;
DisplayExtendedAttributes(hOutputWindow, ExtAttrib -> GlobalUnknowns, ExtAttrib -> NumGlobalUnknowns); break; case HIDP_GET_LINK_COLL_NODES:
OUTSTRING(hOutputWindow, "Link Collection Nodes"); OUTSTRING(hOutputWindow, "====================="); NodeList = (PHIDP_LINK_COLLECTION_NODE) Results -> List; for (Index = 0; Index < Results -> ListLength; Index++) { OUTSTRING(hOutputWindow, "==========================="); vDisplayLinkCollectionNode(NodeList+Index, Index, hOutputWindow); } break;
case HIDP_GET_SCALED_USAGE_VALUE: stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "Scaled usage value: %ld", Results -> ScaledValue); OUTSTRING(hOutputWindow, szTempBuffer);
break;
case HIDP_GET_USAGE_VALUE: stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "Usage value: %lu", Results -> Value); OUTSTRING(hOutputWindow, szTempBuffer); break;
/*
// To display a usage value array, we must extract each of the values
// in the array based on the ReportSize. The ReportSize is not necessarily
// an even byte size so we must use the special extraction routine to get
// each of the values in the array.
*/ case HIDP_GET_USAGE_VALUE_ARRAY:
UsageValueArray = (PCHAR) Results -> List;
for (Index = 0; Index < Results -> ReportCount; Index++) { vCreateUsageValueStringFromArray(UsageValueArray, Results -> BitSize, (USHORT) Index, szTempBuffer); OUTSTRING(hOutputWindow, szTempBuffer); } break;
case HIDP_GET_VALUE_CAPS: case HIDP_GET_SPECIFIC_VALUE_CAPS: ValueCaps = (PHIDP_VALUE_CAPS) Results -> List;
for (Index = 0; Index < (INT) Results -> ListLength; Index++) { OUTSTRING(hOutputWindow, "=========================="); vDisplayValueAttributes(ValueCaps + Index, hOutputWindow); } break;
case HIDP_MAX_DATA_LIST_LENGTH: stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "MaxDataListLength: %u", Results -> Value); OUTSTRING(hOutputWindow, szTempBuffer); break;
case HIDP_MAX_USAGE_LIST_LENGTH: stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "MaxUsageListLength: %u", Results -> Value); OUTSTRING(hOutputWindow, szTempBuffer); break;
/*
// For HidP_UsageListDifference, we need to display both of the make and
// break lists generated by the function. Therefore, we end up creating
// two different usage list strings.
*/ case HIDP_USAGE_LIST_DIFFERENCE: OUTSTRING(hOutputWindow, "Make List"); OUTSTRING(hOutputWindow, "=========");
UsageList = (PUSAGE) Results -> MakeList; Index = 0;
while (0 != *(UsageList+Index) && Index < Results -> ListLength) { vCreateUsageString(UsageList + Index, szTempBuffer);
OUTSTRING(hOutputWindow, szTempBuffer); Index++; }
OUTSTRING(hOutputWindow, "Break List"); OUTSTRING(hOutputWindow, "==========");
UsageList = (PUSAGE) Results -> BreakList; Index = 0;
while (0 != *(UsageList+Index) && Index < Results -> ListLength) { vCreateUsageString(UsageList + Index, szTempBuffer);
OUTSTRING(hOutputWindow, szTempBuffer); Index++; } break;
/*
// These functions simply update the buffer that is specified as the
// input parameter. We must select the correct display buffer mechanism
// based on the ReportType for the call and then update the given report
// in that display mechanism.
*/ case HID_READ_REPORT: case HIDD_GET_FEATURE: case HIDD_GET_INPUT_REPORT: case HIDP_INITIALIZE_REPORT_FOR_ID: case HIDP_SET_BUTTONS: case HIDP_SET_DATA: case HIDP_SET_SCALED_USAGE_VALUE: case HIDP_SET_USAGES: case HIDP_SET_USAGE_VALUE: case HIDP_SET_USAGE_VALUE_ARRAY: case HIDP_UNSET_BUTTONS: case HIDP_UNSET_USAGES: SELECT_ON_REPORT_TYPE(Results -> ReportType, pInputDisplay, pOutputDisplay, pFeatureDisplay, pDisplay);
BufferDisplay_UpdateBuffer(pDisplay, Results -> ReportBuffer); break; } return; }
VOID vExecuteAndDisplayOutput( HWND hOutputWindow, PHID_DEVICE pDevice, INT iFuncCall, PECDISPLAY_PARAMS params ) /*++
RoutineDescription: This routine is a long function that is responsible for retrieving all the paramter for a given function call, setting up the CallParameters structure and then call the execute routine to get the necessary results and status of the operation. It is then responsible for displaying the appropriate status and results if the function did not fail
This routine is a fairly long, complex routine to do a simple task. It may be broken down in future versions to simplify some of the complexity. --*/ { EXTCALL_PARAMS CallParameters; EXTCALL_STATUS CallStatus;
DLGBOX_STATUS iDlgStatus; BOOL ExecuteStatus; PBUFFER_DISPLAY pBufferDisplay; PCHAR pCopyBuffer; PCHAR endp; UINT DlgBoxNumber; BOOL List2Alloc; BOOL MakeListAlloc; BOOL BreakListAlloc;
HID_DEVICE readDevice, writeDevice; BOOL status; HRESULT stringReturn;
/*
// ExecuteAndDisplayOutput needless to say, consists of two parts:
// Executing and Displaying output. The first section involves the
// execution phase where all parameters are filled in if necessary
// and ECDisp_Execute is called
*/
if (IS_NOT_IMPLEMENTED(iFuncCall)) { OUTSTRING(hOutputWindow, "Function not yet implemented"); return; }
/*
// Check first to see if this is a HID_CLEAR_REPORT command. If it is
// all we need to do is get the report buffer that is checked and
// then call the clear buffer command
*/
if (HID_CLEAR_REPORT == iFuncCall) { SELECT_ON_REPORT_TYPE(params -> ReportType, pInputDisplay, pOutputDisplay, pFeatureDisplay, pBufferDisplay);
BufferDisplay_ClearBuffer(pBufferDisplay); return; }
/*
// Need to perform the following steps in order to get the parameters for
// our call and then execute the call:
// 1) Get any additional parameters not supplied by the above dialog
// procedure. This occurs for such functions as:
// HIDP_SET_BUTTONS
// HIDP_SET_DATA
// HIDP_SET_USAGES
// HIDP_SET_USAGE_VALUE
// HIDP_SET_SCALED_USAGE_VALUE
// HIDP_SET_USAGE_VALUE_ARRAY
// HIDP_UNSET_BUTTONS
// HIDP_UNSET_USAGES
// For these functions, a separate dialog box must be called
//
// 2) Fill in the common parameters from the passed in params struct
//
*/
/*
// Step 1: We're storing the values retrieved by these additional dialog
// box in the params struct since we may actually be passed in
// these values in the future instead of getting them here. Hence,
// we won't break any of the code that follows the switch statement
*/
switch (iFuncCall) { case HIDP_SET_BUTTONS: case HIDP_SET_USAGES: case HIDP_UNSET_BUTTONS: case HIDP_UNSET_USAGES:
switch (iFuncCall) { case HIDP_SET_BUTTONS: DlgBoxNumber = IDD_SET_BUTTONS; break;
case HIDP_SET_USAGES: DlgBoxNumber = IDD_SET_USAGES; break;
case HIDP_UNSET_BUTTONS: DlgBoxNumber = IDD_UNSET_BUTTONS; break;
case HIDP_UNSET_USAGES: DlgBoxNumber = IDD_UNSET_USAGES; break; }
iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(DlgBoxNumber), GetParent(hOutputWindow), bSetUsagesDlgProc, (LPARAM) params); /*
// If the above call returns 1, then the dialog box routine
// successfully acquired a string from the user and put the
// pointer to it in params -> szListString.
// Now we need to convert the string to a usage list
*/
if (DLGBOX_OK != iDlgStatus) return;
ExecuteStatus = ConvertStringToUsageList(params -> szListString, ¶ms -> UsageList, ¶ms -> ListLength); free(params -> szListString);
if (!ExecuteStatus) { ECDISP_ERROR(GetParent(hOutputWindow), "Error getting usage list"); return; } break;
case HIDP_GET_EXTENDED_ATTRIBUTES: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_GET_EXT_ATTRIB), GetParent(hOutputWindow), bGetIndexedDlgProc, (LPARAM) params);
if (DLGBOX_OK != iDlgStatus) return;
params -> Index = strtoul(params -> szListString, &endp, 10); if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid index value");
free(params -> szListString); free(params -> szListString2); return; } free(params -> szListString); params -> ListLength = strtoul(params -> szListString2, &endp, 10);
if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid buffer size");
free(params -> szListString2); return; } free(params -> szListString2); break;
case HIDD_GET_INDEXED_STRING: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_GET_INDEX_STRING), GetParent(hOutputWindow), bGetIndexedDlgProc, (LPARAM) params);
if (DLGBOX_OK != iDlgStatus) return;
params -> Index = strtoul(params -> szListString, &endp, 10); if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid index value");
free(params -> szListString); free(params -> szListString2); return; } free(params -> szListString); params -> ListLength = strtoul(params -> szListString2, &endp, 10);
if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid buffer size"); free(params -> szListString2); return; } free(params -> szListString2); break; case HIDD_GET_MS_GENRE_DESCRIPTOR: case HIDD_GET_PHYSICAL_DESCRIPTOR: case HIDD_GET_MANUFACTURER_STRING: case HIDD_GET_PRODUCT_STRING: case HIDD_GET_SERIAL_NUMBER_STRING: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SET_BUFFER_LENGTH), GetParent(hOutputWindow), bSetBufLenDlgProc, (LPARAM) params);
if (DLGBOX_OK != iDlgStatus) return;
params -> ListLength = strtoul(params -> szListString, &endp, 10);
if ('\0' != *endp) { free(params -> szListString); ECDISP_ERROR(GetParent(hOutputWindow), "Invalid buffer length"); return; } free(params -> szListString); break;
case HIDD_SET_NUM_INPUT_BUFFERS: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SET_INPUT_BUFFERS), GetParent(hOutputWindow), bSetInputBuffDlgProc, (LPARAM) params); /*
// If the above call returns 1, then the dialog box routine
// successfully acquired a string from the user and put the
// pointer to it in params -> szListString.
// Now we need to convert the string to a usage list
*/
if (DLGBOX_OK != iDlgStatus) return;
params -> Value = strtoul(params -> szListString, &endp, 10);
if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid value specified");
free(params -> szListString); return; } free(params -> szListString); break;
case HIDP_SET_DATA: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SET_DATA), GetParent(hOutputWindow), bSetDataDlgProc, (LPARAM) params);
if (DLGBOX_OK != iDlgStatus) return;
break;
case HIDP_SET_SCALED_USAGE_VALUE: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SET_SCALED_VALUE), GetParent(hOutputWindow), bSetValueDlgProc, (LPARAM) params); /*
// If the above call returns DLGBOX_OK, then the dialog box routine
// successfully acquired a string from the user and put the
// pointer to it in params -> szListString.
// Now we need to convert the string to a usage list
*/
if (DLGBOX_OK != iDlgStatus) return;
params -> ScaledValue = strtol(params -> szListString, &endp, 10);
if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid scaled usage value");
free(params -> szListString); return; }
free(params -> szListString); break;
case HIDP_SET_USAGE_VALUE: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SET_USAGE_VALUE), GetParent(hOutputWindow), bSetValueDlgProc, (LPARAM) params); /*
// If the above call returns 1, then the dialog box routine
// successfully acquired a string from the user and put the
// pointer to it in params -> szListString.
// Now we need to convert the string to a usage list
*/
if (DLGBOX_OK != iDlgStatus) return;
params -> Value = strtoul(params -> szListString, &endp, 10); if ('\0' != *endp) { ECDISP_ERROR(GetParent(hOutputWindow), "Invalid usage value");
free(params -> szListString); return; } free(params -> szListString); break;
case HIDP_SET_USAGE_VALUE_ARRAY: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SET_USAGE_VALUE_ARRAY), GetParent(hOutputWindow), bSetValueDlgProc, (LPARAM) params);
/*
// If the above call returns 1, then the dialog box routine
// successfully acquired a string from the user and put the
// pointer to it in params -> szListString.
// Now we need to convert the string to a usage list
*/
if (DLGBOX_OK != iDlgStatus) return;
ExecuteStatus = ConvertStringToUlongList(params -> szListString, ¶ms -> pValueList, ¶ms -> ListLength); free(params -> szListString);
if (!ExecuteStatus) { ECDISP_ERROR(GetParent(hOutputWindow), "Error getting list of values"); return; } break;
case HIDP_USAGE_LIST_DIFFERENCE: iDlgStatus = (DLGBOX_STATUS) DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_USAGE_LIST_DIFFERENCE), GetParent(hOutputWindow), bGetUsageDiffDlgProc, (LPARAM) params);
if (DLGBOX_OK != iDlgStatus) { return; }
ExecuteStatus = Strings_StringToUnsignedList(params -> szListString, sizeof(USAGE), 16, (PCHAR *) ¶ms -> UsageList, ¶ms -> ListLength);
if (!ExecuteStatus) { ECDISP_ERROR(GetParent(hOutputWindow), "Error getting list of values");
free(params -> szListString); free(params -> szListString2); return; }
ExecuteStatus = Strings_StringToUnsignedList(params -> szListString2, sizeof(USAGE), 16, (PCHAR *) ¶ms -> UsageList2, ¶ms -> ListLength2);
if (!ExecuteStatus) { ECDISP_ERROR(GetParent(hOutputWindow), "Error getting list of values");
free(params -> szListString); free(params -> szListString2); free(params -> UsageList); return; }
free(params -> szListString); free(params -> szListString2); break; }
/*
// Step 2: Extract the common parameters. It's probably easier
// to simply fill in the spots in call parameters whether they are used
// or not instead of filling in only those that are relevant to a given
// function. The details of some function relevant parameters are
// handled after this.
*/
CallParameters.DeviceHandle = pDevice -> HidDevice; CallParameters.ReportType = params -> ReportType; CallParameters.Ppd = pDevice -> Ppd; CallParameters.UsagePage = params -> UsagePage; CallParameters.Usage = params -> Usage; CallParameters.LinkCollection = params -> LinkCollection; CallParameters.ReportID = params -> ReportID; CallParameters.List = NULL; CallParameters.List2 = NULL; CallParameters.MakeList = NULL; CallParameters.BreakList = NULL; CallParameters.ListLength = 0;
List2Alloc = FALSE; MakeListAlloc = FALSE; BreakListAlloc = FALSE;
/*
// Step 3: Now we'll deal with those functions that require a report buffer of some kind
// which means we'll copy the current buffer of the selected reported
// type
*/
switch (iFuncCall) { case HID_READ_REPORT:
status = OpenHidDevice(pDevice -> DevicePath, TRUE, FALSE, FALSE, FALSE, &readDevice); if (!status) { OUTSTRING(hOutputWindow, "Unable to open device for reading"); } CallParameters.DeviceHandle = readDevice.HidDevice; CallParameters.ReportType = HidP_Input; CallParameters.ReportBuffer = readDevice.InputReportBuffer; CallParameters.ReportLength = readDevice.Caps.InputReportByteLength; break;
case HID_WRITE_REPORT:
status = OpenHidDevice(pDevice -> DevicePath, TRUE, FALSE, FALSE, FALSE, &writeDevice); if (!status) { OUTSTRING(hOutputWindow, "Unable to open device for writing"); } BufferDisplay_CopyCurrentBuffer(pOutputDisplay, writeDevice.OutputReportBuffer);
CallParameters.DeviceHandle = writeDevice.HidDevice; CallParameters.ReportType = HidP_Output; CallParameters.ReportBuffer = writeDevice.OutputReportBuffer; CallParameters.ReportLength = writeDevice.Caps.OutputReportByteLength; break;
case HIDD_GET_INPUT_REPORT: CallParameters.ReportType = HidP_Input; CallParameters.ReportBuffer = pDevice -> InputReportBuffer; CallParameters.ReportLength = pDevice -> Caps.InputReportByteLength; break;
case HIDD_GET_FEATURE: CallParameters.ReportType = HidP_Feature; CallParameters.ReportBuffer = pDevice -> FeatureReportBuffer; CallParameters.ReportLength = pDevice -> Caps.FeatureReportByteLength; break;
case HIDD_GET_INDEXED_STRING: case HIDP_GET_EXTENDED_ATTRIBUTES: CallParameters.Index = params -> Index; CallParameters.ListLength = params -> ListLength; break;
case HIDD_SET_OUTPUT_REPORT: CallParameters.ReportType = HidP_Output; BufferDisplay_CopyCurrentBuffer(pOutputDisplay, pDevice -> OutputReportBuffer); CallParameters.ReportLength = BufferDisplay_GetBufferSize(pOutputDisplay); CallParameters.ReportBuffer = pDevice -> OutputReportBuffer; break;
case HIDD_SET_FEATURE: CallParameters.ReportType = HidP_Feature; BufferDisplay_CopyCurrentBuffer(pFeatureDisplay, pDevice -> FeatureReportBuffer); CallParameters.ReportLength = BufferDisplay_GetBufferSize(pFeatureDisplay); CallParameters.ReportBuffer = pDevice -> FeatureReportBuffer; break;
case HIDP_GET_BUTTONS: case HIDP_GET_BUTTONS_EX: case HIDP_GET_DATA: case HIDP_GET_SCALED_USAGE_VALUE: case HIDP_GET_USAGES: case HIDP_GET_USAGES_EX: case HIDP_GET_USAGE_VALUE: case HIDP_GET_USAGE_VALUE_ARRAY: case HIDP_INITIALIZE_REPORT_FOR_ID: case HIDP_SET_BUTTONS: case HIDP_SET_DATA: case HIDP_SET_SCALED_USAGE_VALUE: case HIDP_SET_USAGES: case HIDP_SET_USAGE_VALUE: case HIDP_SET_USAGE_VALUE_ARRAY: case HIDP_UNSET_BUTTONS: case HIDP_UNSET_USAGES: switch (CallParameters.ReportType) { case HidP_Input: pBufferDisplay = pInputDisplay; pCopyBuffer = pDevice -> InputReportBuffer; break;
case HidP_Output: pBufferDisplay = pOutputDisplay; pCopyBuffer = pDevice -> OutputReportBuffer; break;
case HidP_Feature: pBufferDisplay = pFeatureDisplay; pCopyBuffer = pDevice -> FeatureReportBuffer; break;
} BufferDisplay_CopyCurrentBuffer(pBufferDisplay, pCopyBuffer);
CallParameters.ReportLength = BufferDisplay_GetBufferSize(pBufferDisplay); CallParameters.ReportBuffer = pCopyBuffer; break;
default: CallParameters.ReportLength = 0; CallParameters.ReportBuffer = NULL; }
/*
// Now, we need to deal with those functions which have a List that is
// used for either retrieving or gathering data. There are two different
// cases. The first involves the user inputting a buffer and the system
// performing some action on the buffer, such as SetButtons. We'll also
// the other functions that require one of the union fields to be set.
//
*/
/*
// The second case is where data is retrieved for the device. In this case,
// all we do is specify either the number of elements need for the buffer,
// the execute routine will worry about allocating the correct amount of
// space for those elements. Remember, however, that if the Execute routine
// allocates space, we need to free it up.
*/
/*
// Then there's the third case UsageListDifference which truly changes
// everything. We've got to determine the size of the resulting lists
// is the MaxSize of the other two lists. Plus, we need to insure that
// our buffers are 00 terminated if they are less than the max size, ie
// there not the same size as the larger buffer. This may require
// reallocation of the block.
*/
switch (iFuncCall) { /*
// First Case functions
*/
case HIDP_SET_DATA: CallParameters.List = (PVOID) params -> pDataList; CallParameters.ListLength = params -> ListLength; break;
case HIDP_SET_BUTTONS: case HIDP_UNSET_BUTTONS: case HIDP_SET_USAGES: case HIDP_UNSET_USAGES: CallParameters.List = (PVOID) params -> UsageList; CallParameters.ListLength = params -> ListLength; break;
case HIDP_SET_USAGE_VALUE_ARRAY: CallParameters.List = (PVOID) params -> pValueList; CallParameters.ListLength = params -> ListLength; break;
/*
// Second Case functions
*/
case HIDP_GET_BUTTON_CAPS: case HIDP_GET_SPECIFIC_BUTTON_CAPS: SELECT_ON_REPORT_TYPE(CallParameters.ReportType, pDevice -> Caps.NumberInputButtonCaps, pDevice -> Caps.NumberOutputButtonCaps, pDevice -> Caps.NumberFeatureButtonCaps, CallParameters.ListLength); break;
case HIDP_GET_LINK_COLL_NODES: CallParameters.ListLength = pDevice -> Caps.NumberLinkCollectionNodes; break;
case HIDD_GET_MS_GENRE_DESCRIPTOR: case HIDD_GET_PHYSICAL_DESCRIPTOR: case HIDD_GET_MANUFACTURER_STRING: case HIDD_GET_PRODUCT_STRING: case HIDD_GET_SERIAL_NUMBER_STRING: CallParameters.ListLength = params -> ListLength; break;
case HIDP_GET_VALUE_CAPS: case HIDP_GET_SPECIFIC_VALUE_CAPS: SELECT_ON_REPORT_TYPE(CallParameters.ReportType, pDevice -> Caps.NumberInputValueCaps, pDevice -> Caps.NumberOutputValueCaps, pDevice -> Caps.NumberFeatureValueCaps, CallParameters.ListLength);
case HIDD_GET_FREE_PREPARSED_DATA: CallParameters.ppPd = &CallParameters.Ppd; break;
case HIDP_SET_SCALED_USAGE_VALUE: CallParameters.ScaledValue = params -> ScaledValue; break;
case HIDP_SET_USAGE_VALUE: case HIDD_SET_NUM_INPUT_BUFFERS: CallParameters.Value = params -> Value; break;
/*
// That third case
*/
case HIDP_USAGE_LIST_DIFFERENCE: CallParameters.ListLength = max(params -> ListLength, params -> ListLength2);
CallParameters.List = params -> UsageList; CallParameters.List2 = params -> UsageList2;
if (CallParameters.ListLength > params -> ListLength) { CallParameters.List = (PUSAGE) realloc(params -> UsageList, (params -> ListLength+1) * sizeof(USAGE));
if (NULL == CallParameters.List) { ECDISP_ERROR(GetParent(hOutputWindow), "Error allocating memory");
free(params -> UsageList); free(params -> UsageList2);
return; }
*(((PUSAGE) CallParameters.List) + CallParameters.ListLength - 1) = 0; } else if (CallParameters.ListLength > params -> ListLength2) { CallParameters.List2 = (PUSAGE) realloc(params -> UsageList2, (params -> ListLength+1) * sizeof(USAGE));
if (NULL == CallParameters.List2) { ECDISP_ERROR(GetParent(hOutputWindow), "Error allocating memory");
free(params -> UsageList); free(params -> UsageList2); return; }
*(((PUSAGE) CallParameters.List2) + CallParameters.ListLength - 1) = 0; } List2Alloc = TRUE; MakeListAlloc = TRUE; BreakListAlloc = TRUE; break; }
/*
// Params are now set up and ready to go, let's execute
*/
if (HIDD_GET_FREE_PREPARSED_DATA == iFuncCall) { ExecuteStatus = ECDisp_Execute(HIDD_GET_PREPARSED_DATA, &CallParameters, &CallStatus);
if (!ExecuteStatus) { OUTSTRING(hOutputWindow, "Unknown error: Couldn't execute function"); return; }
DISPLAY_HIDD_STATUS(hOutputWindow, "HidD_GetPreparsedData", CallStatus, stringReturn);
if (!CallStatus.IsHidError) { ExecuteStatus = ECDisp_Execute(HIDD_FREE_PREPARSED_DATA, &CallParameters, &CallStatus);
OUTSTRING(hOutputWindow, "======================="); if (!ExecuteStatus) { OUTSTRING(hOutputWindow, "Unknown error: Couldn't execute function"); return; }
DISPLAY_HIDD_STATUS(hOutputWindow, "HidD_FreePreparsedData", CallStatus, stringReturn); } } else { if ((HID_READ_REPORT == iFuncCall || HID_WRITE_REPORT == iFuncCall) && (!status)) { //
// Indicate there was an error so we don't display anything further
//
CallStatus.IsHidError = TRUE; } else { ExecuteStatus = ECDisp_Execute(iFuncCall, &CallParameters, &CallStatus);
if (!ExecuteStatus) { OUTSTRING(hOutputWindow, "Unknown error: Couldn't execute function"); return; }
if (IS_HIDD_FUNCTION(iFuncCall) || IS_HID_FUNCTION(iFuncCall)) { DISPLAY_HIDD_STATUS(hOutputWindow, GET_FUNCTION_NAME(iFuncCall), CallStatus, stringReturn);
} else { DISPLAY_HIDP_STATUS(hOutputWindow, GET_FUNCTION_NAME(iFuncCall), CallStatus, stringReturn); } } }
/*
// Display the other results only if there wasn't a HID error
*/
if (!CallStatus.IsHidError || (HIDP_STATUS_NULL == CallStatus.HidErrorCode)) { OUTSTRING(hOutputWindow, "=======================");
/*
// Now that general status information has been displayed, we need to
// display the info for the parts that are dependent on the function being
// called
*/ ECDisp_DisplayOutput(hOutputWindow, iFuncCall, &CallParameters); }
if (CallParameters.List != NULL) { free(CallParameters.List); }
if (List2Alloc && CallParameters.List2 != NULL) { free(CallParameters.List2); }
if (MakeListAlloc && CallParameters.MakeList != NULL) { free(CallParameters.MakeList); }
if (BreakListAlloc && CallParameters.BreakList != NULL) { free(CallParameters.BreakList); }
return; }
VOID BuildReportIDList( IN PHIDP_BUTTON_CAPS phidButtonCaps, IN USHORT nButtonCaps, IN PHIDP_VALUE_CAPS phidValueCaps, IN USHORT nValueCaps, OUT PUCHAR *ppReportIDList, OUT INT *nReportIDs ) /*++
RoutineDescription: This routine builds a list of report IDs that are listed in the passed in set of ButtonCaps and ValueCaps structure. It allocates a buffer to store all the ReportIDs, if it can. Otherwise the buffer is returned as NULL.
Currently, this routine has no purpose in the HClient program. It was written for some purpose which never materialized but was left in because it might be useful in the future. --*/ { INT nAllocatedIDs; INT nFoundIDs; INT nWalkCount; USHORT usIndex; BOOL fIDFound; UCHAR *pucBuffer; UCHAR *pucNewBuffer; UCHAR *pucWalk; UCHAR ucReportID; PHIDP_BUTTON_CAPS pButtonWalk; PHIDP_VALUE_CAPS pValueWalk;
/*
// Initialize the output parameters in case there is some sort of failure
*/
*nReportIDs = 0; *ppReportIDList = NULL;
if (0 == nButtonCaps && 0 == nValueCaps) return;
/*
// Initialize the beginning array size to 2 report IDs and alloc space
// for those IDs. If we need to add more report IDs we allocate more
// space
*/
nAllocatedIDs = 2; nFoundIDs = 0; pButtonWalk = phidButtonCaps; pValueWalk = phidValueCaps; pucBuffer = (UCHAR *) malloc(sizeof(UCHAR) * nAllocatedIDs); if (NULL == pucBuffer) return;
/*
// Beginning with the button caps and then going to the value caps do the
// following
//
// 1) Take the report ID and search the array of report IDs looking for
// an existing report ID and add to the array if not there.
//
// 2) Add the report ID to the array in sorted order that way we sort the
// array at any time.
//
// 3) Must also realloc the array if we run out of array space
*/
for (usIndex = 0; usIndex < nButtonCaps; usIndex++, pButtonWalk++) { ucReportID = pButtonWalk -> ReportID; pucWalk = pucBuffer; nWalkCount = 0; fIDFound = FALSE;
while (!fIDFound && nWalkCount < nFoundIDs) { if (*pucWalk == ucReportID) { fIDFound = TRUE; } else if (ucReportID > *pucWalk) { pucWalk++; nWalkCount++; } }
if (!fIDFound) { if (nFoundIDs == nAllocatedIDs) { nAllocatedIDs *= 2;
pucNewBuffer = (UCHAR *) realloc(pucBuffer, sizeof(UCHAR) * nAllocatedIDs);
if (NULL == pucNewBuffer) { free(pucBuffer); pucBuffer = NULL; return; } else { pucBuffer = pucNewBuffer; }
pucWalk = pucBuffer + nWalkCount; }
/*
// At this point, pucWalk points to the smallest ReportID in the
// buffer that is greater than the ReportID we want to insert.
// We need to bump all reportIDs beginning at pucWalk up one
// spot and insert the new ReportID at pucWalk
*/
memmove (pucWalk+1, pucWalk, (nFoundIDs - nWalkCount) * sizeof(UCHAR)); *pucWalk = ucReportID; nFoundIDs++; } }
*ppReportIDList = pucBuffer; *nReportIDs = nFoundIDs; return; }
LRESULT CALLBACK bSetUsagesDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG: pParams = (PECDISPLAY_PARAMS) lParam;
SetDlgItemIntHex(hDlg, IDC_USAGE_PAGE, pParams -> UsagePage, 2); break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_USAGE_LIST));
if (StringLength > 0) { pParams -> szListString = (PCHAR) malloc(StringLength+1); if (NULL == pParams -> szListString) { ECDISP_ERROR(hDlg, "Error allocating memory"); RetValue = DLGBOX_ERROR; } else { GetWindowText(GetDlgItem(hDlg, IDC_USAGE_LIST), pParams -> szListString, StringLength+1);
RetValue = DLGBOX_OK; } } else { pParams -> szListString = NULL; RetValue = DLGBOX_CANCEL; }
EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bSetValueDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG:
pParams = (PECDISPLAY_PARAMS) lParam;
SetDlgItemIntHex(hDlg, IDC_USAGE_PAGE, pParams -> UsagePage, sizeof(USAGE));
SetDlgItemIntHex(hDlg, IDC_USAGE, pParams -> Usage, sizeof(USAGE)); break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_VALUE));
if (StringLength > 0) { pParams -> szListString = (PCHAR) malloc(StringLength+1); if (NULL == pParams -> szListString) { ECDISP_ERROR(hDlg, "Error allocating memory");
RetValue = DLGBOX_ERROR; } else { GetWindowText(GetDlgItem(hDlg, IDC_VALUE), pParams -> szListString, StringLength+1);
RetValue = DLGBOX_OK; } } else { pParams -> szListString = NULL; RetValue = DLGBOX_CANCEL; }
EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bSetInputBuffDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG: pParams = (PECDISPLAY_PARAMS) lParam; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_INPUT_BUFFERS));
if (StringLength > 0) { pParams -> szListString = (PCHAR) malloc(StringLength+1);
if (NULL == pParams -> szListString) { ECDISP_ERROR(hDlg, "Error allocating memory");
RetValue = DLGBOX_ERROR; } else { GetWindowText(GetDlgItem(hDlg, IDC_INPUT_BUFFERS), pParams -> szListString, StringLength+1);
RetValue = DLGBOX_OK; } } else { pParams -> szListString = NULL; RetValue = DLGBOX_CANCEL; }
EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bSetDataDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static CHAR DataString[TEMP_BUFFER_SIZE]; static PECDISPLAY_PARAMS pParams; UINT IndexValue; ULONG Value; BOOL lpTranslated; DLGBOX_STATUS RetValue; PCHAR endp; INT ListBoxStatus; PHIDP_DATA DataList; PHIDP_DATA CurrData; ULONG DataListLength; ULONG Index; HRESULT stringReturn; INT iReturn;
switch (message) { case WM_INITDIALOG:
pParams = (PECDISPLAY_PARAMS) lParam; SendMessage(GetDlgItem(hDlg, IDC_VALUE), EM_SETLIMITTEXT, (WPARAM) 1024, 0); break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_ADD_DATA: IndexValue = GetDlgItemInt(hDlg, IDC_INDEX, &lpTranslated, FALSE); if (!lpTranslated) { ECDISP_ERROR(hDlg, "Invalid index value: must be unsigned integer"); break; } if (0 == GetWindowText(GetDlgItem(hDlg, IDC_VALUE), DataString, 1023)) { ECDISP_ERROR(hDlg, "Invalid data value"); break; }
CharUpperBuff(DataString, lstrlen(DataString));
if (0 == lstrcmp(DataString, "TRUE")) { Value = 1; } else if (0 == lstrcmp(DataString, "FALSE")) { Value = 0; } else { Value = strtoul(DataString, &endp, 10); if (*endp != '\0') { ECDISP_ERROR(hDlg, "Invalid data value"); break; } } stringReturn = StringCbPrintf(DataString, TEMP_BUFFER_SIZE, SETDATA_LISTBOX_FORMAT, IndexValue, Value);
ListBoxStatus = (INT) SendMessage(GetDlgItem(hDlg, IDC_DATA_LIST), LB_ADDSTRING, 0, (LPARAM) DataString);
if (CB_ERR == ListBoxStatus || CB_ERRSPACE == ListBoxStatus) { ECDISP_ERROR(hDlg, "Error adding string to data list"); break; } break;
case IDC_REMOVE_DATA: SendMessage(GetDlgItem(hDlg, IDC_DATA_LIST), LB_DELETESTRING, SendMessage(GetDlgItem(hDlg, IDC_DATA_LIST), LB_GETCURSEL, 0, 0), 0); break;
case IDOK: DataListLength = (ULONG) SendMessage(GetDlgItem(hDlg, IDC_DATA_LIST), LB_GETCOUNT, 0, 0);
if (0 != DataListLength) { DataList = malloc(DataListLength * sizeof(HIDP_DATA)); if (NULL == DataList) { ECDISP_ERROR(hDlg, "Error allocating memory");
DataListLength = 0; RetValue = DLGBOX_CANCEL; break; } for (Index = 0, CurrData = DataList; Index < DataListLength; Index++, CurrData++) { SendMessage(GetDlgItem(hDlg, IDC_DATA_LIST), LB_GETTEXT, Index, (LPARAM) DataString);
iReturn = sscanf(DataString, SETDATA_LISTBOX_FORMAT, &IndexValue, &Value);
CurrData -> DataIndex = (USHORT) IndexValue; CurrData -> RawValue = Value; } RetValue = DLGBOX_OK; } else { DataList = NULL; RetValue = DLGBOX_CANCEL; }
pParams -> pDataList = DataList; pParams -> ListLength = DataListLength; EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bSetBufLenDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG:
pParams = (PECDISPLAY_PARAMS) lParam; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_BUFFER_LENGTH));
if (StringLength > 0) { pParams -> szListString = (PCHAR) malloc(StringLength+1); if (NULL == pParams -> szListString) { ECDISP_ERROR(hDlg, "Error allocating memory");
RetValue = DLGBOX_ERROR;
} else { GetWindowText(GetDlgItem(hDlg, IDC_BUFFER_LENGTH), pParams -> szListString, StringLength+1);
RetValue = DLGBOX_OK; } } else { pParams -> szListString = NULL; RetValue = DLGBOX_CANCEL; }
EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bSetInputBuffersDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG:
pParams = (PECDISPLAY_PARAMS) lParam; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_INPUT_BUFFERS));
if (StringLength > 0) { pParams -> szListString = (PCHAR) malloc(StringLength+1);
if (NULL == pParams -> szListString) { ECDISP_ERROR(hDlg, "Error allocating memory"); RetValue = DLGBOX_ERROR; } else { GetWindowText(GetDlgItem(hDlg, IDC_INPUT_BUFFERS), pParams -> szListString, StringLength+1 ); RetValue = DLGBOX_OK; } } else { pParams -> szListString = NULL; RetValue = DLGBOX_CANCEL; }
EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bGetIndexedDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; INT StringLength2; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG:
pParams = (PECDISPLAY_PARAMS) lParam; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_INDEX)); StringLength2 = GetWindowTextLength(GetDlgItem(hDlg, IDC_BUFFER_LENGTH));
if (StringLength <= 0 || StringLength2 <= 0) { pParams -> szListString = NULL; pParams -> szListString2 = NULL; RetValue = DLGBOX_CANCEL; EndDialog(hDlg, DLGBOX_CANCEL); }
pParams -> szListString = (PCHAR) malloc(StringLength+1); pParams -> szListString2 = (PCHAR) malloc(StringLength2+1);
if (NULL == pParams -> szListString || NULL == pParams -> szListString2) { ECDISP_ERROR(hDlg, "Error allocating memory");
if (NULL != pParams -> szListString) free(pParams -> szListString);
if (NULL != pParams -> szListString2) free(pParams -> szListString2);
RetValue = DLGBOX_ERROR; } else { GetWindowText(GetDlgItem(hDlg, IDC_INDEX), pParams -> szListString, StringLength+1);
GetWindowText(GetDlgItem(hDlg, IDC_BUFFER_LENGTH), pParams -> szListString2, StringLength2+1);
RetValue = DLGBOX_OK; } EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
LRESULT CALLBACK bGetUsageDiffDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static PECDISPLAY_PARAMS pParams; INT StringLength; INT StringLength2; DLGBOX_STATUS RetValue;
switch (message) { case WM_INITDIALOG:
pParams = (PECDISPLAY_PARAMS) lParam; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: StringLength = GetWindowTextLength(GetDlgItem(hDlg, IDC_USAGE_LIST1)); StringLength2 = GetWindowTextLength(GetDlgItem(hDlg, IDC_USAGE_LIST2));
if (StringLength <= 0) { pParams -> szListString = NULL; } else { pParams -> szListString = (PCHAR) malloc(StringLength+1); if (NULL == pParams -> szListString) { ECDISP_ERROR(hDlg, "Error allocating memory");
EndDialog(hDlg, DLGBOX_ERROR); break; } }
if (StringLength2 <= 0) { pParams -> szListString2 = NULL; } else { pParams -> szListString2 = (PCHAR) malloc(StringLength2+1); if (NULL == pParams -> szListString2) { ECDISP_ERROR(hDlg, "Error allocating memory");
if (NULL != pParams -> szListString) { free(pParams -> szListString); } EndDialog(hDlg, DLGBOX_ERROR); break; } }
if ( !(pParams->szListString) ) { GetWindowText(GetDlgItem(hDlg, IDC_USAGE_LIST1), pParams -> szListString, StringLength+1); }
if ( !(pParams->szListString2) ) { GetWindowText(GetDlgItem(hDlg, IDC_USAGE_LIST2), pParams -> szListString2, StringLength2+1); }
RetValue = DLGBOX_OK;
EndDialog(hDlg, RetValue); break;
case IDCANCEL: EndDialog(hDlg, DLGBOX_CANCEL); break; } break; } return (FALSE); }
BOOL ConvertStringToUsageList( IN OUT PCHAR InString, OUT PUSAGE *UsageList, OUT PULONG nUsages ) /*++
RoutineDescription: This routine converts a string of values into a string of usages which are currently 2 byte values. We use base 16 to specify that the usages should be expressed as hexidecimal numbers. --*/ { return (Strings_StringToUnsignedList(InString, sizeof(ULONG), 16, (PCHAR *) UsageList, nUsages)); }
BOOL ConvertStringToUlongList( IN OUT PCHAR InString, OUT PULONG *UlongList, OUT PULONG nUlongs ) /*++
RoutineDescription This routine converts a string of values into a string of ulongs which are currently 2 byte values. It requires that the numbers in the string be in base 10 --*/ { return (Strings_StringToUnsignedList(InString, sizeof(ULONG), 10, (PCHAR *) UlongList, nUlongs)); }
BOOL SetDlgItemIntHex( HWND hDlg, INT nIDDlgItem, UINT uValue, INT nBytes ) { char szTempBuff[] = "0x00000000"; int iEndIndex, iWidth; HRESULT stringReturn;
assert (1 == nBytes || 2 == nBytes || 4 == nBytes);
/*
// Determine the width necessary to store the value
*/
stringReturn = StringCbPrintf(szTempBuff, (sizeof(szTempBuff)), "0x%*X", (nBytes*2), uValue);
SetDlgItemText(hDlg, nIDDlgItem, szTempBuff);
return (TRUE); }
VOID ECDisp_MakeGUIDString( IN GUID guid, OUT CHAR szString[], IN UINT uiBuffSize ) { CHAR szCharString[18]; INT i; HRESULT stringReturn;
for (i = 0; i < 8; i++) { stringReturn = StringCbPrintf(&(szCharString[i]), sizeof(szCharString), "%x", guid.Data4[i]); } stringReturn = StringCbPrintf(szString, uiBuffSize, "%x-%x%x-%s", guid.Data1, guid.Data2, guid.Data3, szCharString); return; }
PCHAR ECDisp_GetHidAppStatusString( NTSTATUS StatusCode ) { static CHAR hidString[128]; HRESULT stringReturn;
switch (StatusCode) { case HIDP_STATUS_SUCCESS: return ("Success");
case HIDP_STATUS_NULL: return ("Status NULL");
case HIDP_STATUS_INVALID_PREPARSED_DATA: return ("Invalid Preparsed Data");
case HIDP_STATUS_INVALID_REPORT_TYPE: return ("Invalid Report Type");
case HIDP_STATUS_INVALID_REPORT_LENGTH: return ("Invalid Report Length");
case HIDP_STATUS_USAGE_NOT_FOUND: return ("Usage not found");
case HIDP_STATUS_VALUE_OUT_OF_RANGE: return ("Value out of range");
case HIDP_STATUS_BAD_LOG_PHY_VALUES: return ("Bad logical physical values");
case HIDP_STATUS_BUFFER_TOO_SMALL: return ("Buffer too small");
case HIDP_STATUS_INTERNAL_ERROR: return ("Internal error");
case HIDP_STATUS_I8242_TRANS_UNKNOWN: return ("I8242 Translation unknown");
case HIDP_STATUS_INCOMPATIBLE_REPORT_ID: return ("Incompatible report ID");
case HIDP_STATUS_NOT_VALUE_ARRAY: return ("Not value array");
case HIDP_STATUS_IS_VALUE_ARRAY: return ("Is value array");
case HIDP_STATUS_DATA_INDEX_NOT_FOUND: return ("Data index not found");
case HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE: return ("Data index out of range");
case HIDP_STATUS_BUTTON_NOT_PRESSED: return ("Button not pressed");
case HIDP_STATUS_REPORT_DOES_NOT_EXIST: return ("Report does not exist");
case HIDP_STATUS_NOT_IMPLEMENTED: return ("Not implemented");
default: stringReturn = StringCbPrintf(hidString, sizeof(hidString), "Unknown HID Status error: 0x%x", StatusCode); return (hidString); } }
BOOL ECDisp_ConvertUlongListToValueList( IN PULONG UlongList, IN ULONG nUlongs, IN USHORT BitSize, IN USHORT ReportCount, OUT PCHAR *ValueList, OUT PULONG ValueListSize ) /*++
RoutineDescription: This routine takes a list of ULong values and formats a value list that is used as input to HidP_SetUsageValueArray. Unfortunately, this HidP function requires the caller to format the input buffer which means taking each of the values in Ulong, truncating their values to meet bit size and then set those bits at the appropriate spot in the buffer. That is the purpose of this function
The function will return TRUE if everything succeeded, FALSE otherwise. --*/ {
ULONG ulMask; PCHAR List; INT iByteIndex; INT iByteOffset; ULONG UlongIndex; ULONG ListSize; USHORT BitsToAdd; USHORT nBits; ULONG ulValue; UCHAR LowByte;
*ValueList = NULL; *ValueListSize = 0; //
// Do some parameter validation...ReportCount should never be zero.
//
if (0 == ReportCount) { SetLastError(ERROR_INVALID_PARAMETER);
return (FALSE); }
//
// Check the number of ulongs passed in is actually less than or equal
// to the report count and if not, use only the first ReportCount
// number of ULongs.
//
if (nUlongs > ReportCount) { nUlongs = ReportCount; }
/*
// Allocate our buffer for the value list and return FALSE if it couldn't
// be done
*/
ListSize = ROUND_TO_NEAREST_BYTE(BitSize * ReportCount); List = (PCHAR) malloc(ListSize);
if (NULL == List) { SetLastError(ERROR_OUTOFMEMORY); return (FALSE); }
/*
// Initialize the buffer to all zeroes
*/
memset(List, 0x00, ListSize);
/*
// Buffer has been allocated let's convert those values
*/
/*
// Determine the mask that will be used to retrieve the cared about bits
// of our value
*/
ulMask = (sizeof(ULONG)*8 == BitSize) ? ULONG_MAX : (1 << BitSize)-1;
/*
// Initialize the iByteIndex and iByteOffset fields before entering the
// conversion loop.
*/
iByteIndex = 0; iByteOffset = 0;
/*
// This is the main conversion loop. It performs the following steps on
// each Ulong in the ulong list
// 1) Sets BitsToAdd = BitSize
// 2) Gets the ulValue and the masks off the upper bits that we don't
// care about.
// 3) Determines how many bits can fit at the current byte index based
// on the current byte offset and the number of bits left to add
// 4) Retrieve those bits, shift them to the correct position and
// use bitwise or to get the correct values in the buffer
// 5) Increment the byte index and set our new byte offset
// 6) Shift our Ulong value right to get rid of least significant bits
// that have already been added
// 7) Repeat through step 3 until no more bits to add
*/
for (UlongIndex = 0; UlongIndex < nUlongs; UlongIndex++) { BitsToAdd = BitSize;
ulValue = *(UlongList + UlongIndex) & ulMask;
while (BitsToAdd > 0) { nBits = min (8 - iByteOffset, BitsToAdd); LowByte = (UCHAR) (ulValue & 0xFF); LowByte = LowByte << iByteOffset;
*(List+iByteIndex) |= LowByte;
iByteIndex = (iByteOffset+nBits) >= 8 ? iByteIndex+1 : iByteIndex; iByteOffset = (iByteOffset + nBits) % 8;
BitsToAdd -= nBits;
ulValue = ulValue >> nBits; } } *ValueList = List; *ValueListSize = ListSize;
return (TRUE); }
PCHAR ResolveFunctionName( INT Index ) { PCHAR FuncName;
if (IS_HIDD_FUNCTION(Index) || IS_HID_FUNCTION(Index)) { FuncName = DeviceCalls[Index-1].szFunctionName; } else { FuncName = PpdCalls[Index-HID_DEVCALLS-1].szFunctionName; }
return (FuncName); }
VOID DisplayExtendedAttributes( IN HWND OutputWindow, IN PHIDP_UNKNOWN_TOKEN UnknownList, IN ULONG UnknownListLength ) { PHIDP_UNKNOWN_TOKEN current; ULONG index; HRESULT stringReturn;
stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "Number of attributes: %d", UnknownListLength); OUTSTRING(OutputWindow, szTempBuffer); current = UnknownList; for (index = 0; index < UnknownListLength; index++) { stringReturn = StringCbPrintf(szTempBuffer, TEMP_BUFFER_SIZE, "Token: %d BitField: 0x%X", current -> Token, current -> BitField); OUTSTRING(OutputWindow, szTempBuffer); }
return; }
|