2025-04-27 07:49:33 -04:00

324 lines
10 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
locate.c
Abstract:
This module contains the code
for finding, adding, removing, and identifying hid devices.
Environment:
Kernel & user mode
@@BEGIN_DDKSPLIT
Revision History:
Nov-96 : Created by Kenneth D. Ray
@@END_DDKSPLIT
--*/
#include <basetyps.h>
#include <stdlib.h>
#include <wtypes.h>
#include <setupapi.h>
#include <initguid.h>
#include <stdio.h>
#include <winioctl.h>
#include "gameport.h"
#include "game.h"
#define USAGE "Usage: gameenum [-e] [-r]\n" \
"\t -e Expose -hardware\n" \
"\t -r Remove hardware\n"
BOOLEAN bExpose,bRemove;
__cdecl main (int argc, char *argv[])
{
PGAME_PORT GamePorts; // A array of struct _GAME_PORT.
ULONG NumberDevices; // the length in elements of this array.
bExpose = bRemove = FALSE;
if(argc <2) {
end: printf(USAGE);
exit(0);
}
if(argv[1][0] == '-')
{
if(argv[1][1] == 'e' || argv[1][1] == 'E')
bExpose = TRUE;
else if(argv[1][1] == 'r' || argv[1][1] == 'R')
bRemove = TRUE;
else
goto end;
}
else
goto end;
if( !FindKnownGamePorts (&GamePorts, &NumberDevices) )
printf("Error: FindKnownGamePorts returned FALSE\n");
return 0;
}
BOOLEAN
OpenGamePort (
IN HDEVINFO HardwareDeviceInfo,
IN PSP_DEVICE_INTERFACE_DATA DeviceInfoData,
IN OUT PGAME_PORT GamePort
);
BOOLEAN
FindKnownGamePorts (
OUT PGAME_PORT * GamePorts, // A array of struct _GAME_PORT.
OUT PULONG NumberDevices // the length in elements of this array.
)
/*++
Routine Description:
Do the required PnP things in order to find, the all the HID devices in
the system at this time.
--*/
{
HDEVINFO hardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA deviceInfoData;
ULONG i;
BOOLEAN done;
PGAME_PORT gamePortInst;
LPGUID gamePortGuid;
gamePortGuid = (LPGUID) &GUID_GAMEENUM_BUS_ENUMERATOR;
*GamePorts = NULL;
*NumberDevices = 0;
//
// Open a handle to the plug and play dev node.
//
hardwareDeviceInfo = SetupDiGetClassDevs (
gamePortGuid,
NULL, // Define no enumerator (global)
NULL, // Define no
(DIGCF_PRESENT | // Only Devices present
DIGCF_DEVICEINTERFACE)); // Function class devices.
//
// Take a wild guess to start
//
*NumberDevices = 4;
done = FALSE;
deviceInfoData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
i=0;
while (!done) {
*NumberDevices *= 2;
if (*GamePorts) {
*GamePorts =
realloc (*GamePorts, (*NumberDevices * sizeof (GAME_PORT)));
} else {
*GamePorts = calloc (*NumberDevices, sizeof (GAME_PORT));
}
if (NULL == *GamePorts) {
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
return FALSE;
}
gamePortInst = *GamePorts + i;
for (; i < *NumberDevices; i++, gamePortInst++) {
if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
0, // No care about specific PDOs
gamePortGuid,
i,
&deviceInfoData)) {
if( !OpenGamePort (hardwareDeviceInfo, &deviceInfoData, gamePortInst) )
printf("Error: OpenGamePort returned FALSE\n");
} else {
if (ERROR_NO_MORE_ITEMS == GetLastError()) {
done = TRUE;
break;
}
}
}
}
*NumberDevices = i;
SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
return TRUE;
}
BOOLEAN
OpenGamePort (
IN HDEVINFO HardwareDeviceInfo,
IN PSP_DEVICE_INTERFACE_DATA DeviceInfoData,
IN OUT PGAME_PORT GamePort
)
/*++
RoutineDescription:
Given the HardwareDeviceInfo, representing a handle to the plug and
play information, and deviceInfoData, representing a specific hid device,
open that device and fill in all the relivant information in the given
HID_DEVICE structure.
return if the open and initialization was successfull or not.
--*/
{
PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = NULL;
ULONG predictedLength = 0;
ULONG requiredLength = 0;
ULONG i, bytes;
GAMEENUM_REMOVE_HARDWARE remove;
//
// allocate a function class device data structure to receive the
// goods about this particular device.
//
SetupDiGetDeviceInterfaceDetail (
HardwareDeviceInfo,
DeviceInfoData,
NULL, // probing so no output buffer yet
0, // probing so output buffer length of zero
&requiredLength,
NULL); // not interested in the specific dev-node
predictedLength = requiredLength;
// sizeof (SP_FNCLASS_DEVICE_DATA) + 512;
functionClassDeviceData = malloc (predictedLength);
if (functionClassDeviceData == NULL) {
printf("Allocation failed, could not get details!\n");
return FALSE;
}
functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
//
// Retrieve the information from Plug and Play.
//
if (! SetupDiGetDeviceInterfaceDetail (
HardwareDeviceInfo,
DeviceInfoData,
functionClassDeviceData,
predictedLength,
&requiredLength,
NULL)) {
printf("Error in SetupDiGetDeviceInterfaceDetail\n");
free (functionClassDeviceData);
return FALSE;
}
printf("Opening %s\n", functionClassDeviceData->DevicePath);
GamePort->File = CreateFile (
functionClassDeviceData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0, // FILE_SHARE_READ | FILE_SHARE_WRITE
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING, // No special create flags
0, // No special attributes
NULL); // No template file
if (INVALID_HANDLE_VALUE == GamePort->File) {
printf("Error in CreateFile: %x", GetLastError());
free (functionClassDeviceData);
return FALSE;
}
printf("File Opened!!!\n");
GamePort->Desc.Size = sizeof (GamePort->Desc);
if (!DeviceIoControl (GamePort->File,
IOCTL_GAMEENUM_PORT_DESC,
&GamePort->Desc, sizeof (GamePort->Desc),
&GamePort->Desc, sizeof (GamePort->Desc),
&bytes, NULL)) {
printf("Error in DeviceIoctl IOCTL_GAMEENUM_PORT_DESC: %x", GetLastError());
free (functionClassDeviceData);
return FALSE;
}
printf("Description: Size (%d), Handle (0x%p), Address (0x%p) \n",
GamePort->Desc.Size,
GamePort->Desc.PortHandle,
GamePort->Desc.PortAddress);
//
// Set the port up
//
if(bExpose) {
printf("\nThis handle is not valid for remove!!!\n\nExposing port\n");
GamePort->Hardware = malloc (bytes = (sizeof (GAMEENUM_EXPOSE_HARDWARE) +
GAME_HARDWARE_IDS_LENGTH));
if (GamePort->Hardware == NULL) {
printf("Allocation failed, could not expose hardware!\n");
return FALSE;
}
GamePort->Hardware->Size = sizeof (GAMEENUM_EXPOSE_HARDWARE);
GamePort->Hardware->PortHandle = GamePort->Desc.PortHandle;
printf("Enter Number of Joysticks:");
scanf("%d",&GamePort->Hardware->NumberJoysticks);
printf("Enter Number of Buttons:");
scanf("%d", &GamePort->Hardware->NumberButtons);
printf("Enter Number of Axes:");
scanf("%d", &GamePort->Hardware->NumberAxis);
memcpy (GamePort->Hardware->HardwareIDs,
GAME_HARDWARE_IDS,
GAME_HARDWARE_IDS_LENGTH);
if (!DeviceIoControl (GamePort->File,
IOCTL_GAMEENUM_EXPOSE_HARDWARE,
GamePort->Hardware, bytes,
GamePort->Hardware, bytes,
&bytes, NULL)) {
free (functionClassDeviceData);
free (GamePort->Hardware);
GamePort->Hardware = NULL;
printf("Error in DeviceIoctl IOCTL_GAMEENUM_EXPOSE_HARDWARE: 0x%x\n", GetLastError());
return FALSE;
}
printf("Hardware handle 0x%p <----- Save this handle!!!\n",GamePort->Hardware->HardwareHandle);
printf("\t\tGameEnum -r will not be able retrieve it for you.\n");
free (GamePort->Hardware);
GamePort->Hardware = NULL;
}
if(bRemove) {
printf("Removing port\n");
remove.Size = bytes = sizeof (remove);
printf("Enter hardware handle: ");
scanf("%x",&remove.HardwareHandle);
printf("Entered Handle: %p", remove.HardwareHandle);
if (!DeviceIoControl (GamePort->File,
IOCTL_GAMEENUM_REMOVE_HARDWARE,
&remove, bytes,
&remove, bytes,
&bytes, NULL)) {
printf("Error in DeviceIoctl IOCTL_GAMEENUM_REMOVE_HARDWARE: 0x%x\n", GetLastError());
return FALSE;
}
}
free (functionClassDeviceData);
return TRUE;
}