#include "OISConfig.h" #ifdef OIS_WIN32_WIIMOTE_SUPPORT //cWiimote 0.2 by Kevin Forbes (http://simulatedcomicproduct.com) //This code is public domain, and comes with no warranty. The user takes full responsibility for anything that happens as a result from using this code. //This was based in part on Alan Macek 's USB interface library //Edited for Toshiba Stack support (hopefully also all others) by //Sean Stellingwerff (http://sean.stellingwerff.com) using information //gathered from http://www.lvr.com/hidpage.htm (Thanks a million! :D) //#include "stdafx.h" #include "hiddevice.h" extern "C" { #include "hidsdi.h" #include } #pragma comment(lib, "setupapi.lib") #pragma comment(lib, "hid.lib") HIDP_CAPS Capabilities; PSP_DEVICE_INTERFACE_DETAIL_DATA detailData; cHIDDevice::cHIDDevice() : mConnected(false), mHandle(NULL), mEvent(NULL) { } cHIDDevice::~cHIDDevice() { if (mConnected) { Disconnect(); } } bool cHIDDevice::Disconnect() { bool retval = false; if (mConnected) { retval = (CloseHandle(mHandle) == TRUE && CloseHandle(mEvent) == TRUE); mConnected = false; } return retval; } bool cHIDDevice::Connect(unsigned short device_id, unsigned short vendor_id, int index) { if (mConnected) { if (!Disconnect()) { return false; } } // Find the wiimote(s) //for (int i = 0; i <= index; i++) OpenDevice( device_id, vendor_id, index ); return mConnected; } bool cHIDDevice::OpenDevice(unsigned short device_id, unsigned short vendor_id, int index) { //Use a series of API calls to find a HID with a specified Vendor IF and Product ID. HIDD_ATTRIBUTES Attributes; SP_DEVICE_INTERFACE_DATA devInfoData; bool LastDevice = FALSE; bool MyDeviceDetected = FALSE; int MemberIndex = 0; int MembersFound = 0; GUID HidGuid; ULONG Length; LONG Result; HANDLE hDevInfo; ULONG Required; Length = 0; detailData = NULL; mHandle=NULL; HidD_GetHidGuid(&HidGuid); hDevInfo=SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); devInfoData.cbSize = sizeof(devInfoData); MemberIndex = 0; MembersFound = 0; LastDevice = FALSE; do { Result=SetupDiEnumDeviceInterfaces(hDevInfo, 0, &HidGuid, MemberIndex, &devInfoData); if (Result != 0) { Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, NULL, 0, &Length, NULL); detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length); detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, detailData, Length, &Required, NULL); mHandle=CreateFile(detailData->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING, 0, NULL); Attributes.Size = sizeof(Attributes); Result = HidD_GetAttributes(mHandle, &Attributes); //Is it the desired device? MyDeviceDetected = FALSE; if (Attributes.VendorID == vendor_id) { if (Attributes.ProductID == device_id) { if (MembersFound == index) { //Both the Vendor ID and Product ID match. //printf("Wiimote found!\n"); mConnected = true; GetCapabilities(); WriteHandle=CreateFile(detailData->DevicePath, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL); MyDeviceDetected = TRUE; PrepareForOverlappedTransfer(); mEvent = CreateEvent(NULL, TRUE, TRUE, ""); mOverlapped.Offset = 0; mOverlapped.OffsetHigh = 0; mOverlapped.hEvent = mEvent; } else { //The Product ID doesn't match. CloseHandle(mHandle); } MembersFound++; } } else { CloseHandle(mHandle); } free(detailData); } else { LastDevice=TRUE; } MemberIndex = MemberIndex + 1; } while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE)); SetupDiDestroyDeviceInfoList(hDevInfo); return MyDeviceDetected; } bool cHIDDevice::WriteToDevice(unsigned const char * OutputReport, int num_bytes) { bool retval = false; if (mConnected) { DWORD bytes_written; retval = (WriteFile( WriteHandle, OutputReport, num_bytes, &bytes_written, &mOverlapped) == TRUE); retval = retval && bytes_written == num_bytes; } return retval; } void cHIDDevice::PrepareForOverlappedTransfer() { //Get a handle to the device for the overlapped ReadFiles. ReadHandle=CreateFile(detailData->DevicePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); } void cHIDDevice::GetCapabilities() { //Get the Capabilities structure for the device. PHIDP_PREPARSED_DATA PreparsedData; HidD_GetPreparsedData(mHandle, &PreparsedData); HidP_GetCaps(PreparsedData, &Capabilities); //No need for PreparsedData any more, so free the memory it's using. HidD_FreePreparsedData(PreparsedData); } bool cHIDDevice::ReadFromDevice(unsigned const char * buffer, int max_bytes, int & bytes_read, int timeout) { bool retval = false; if (mConnected) { ReadFile( ReadHandle, (LPVOID)buffer,max_bytes,(LPDWORD)&bytes_read,(LPOVERLAPPED) &mOverlapped); DWORD Result = WaitForSingleObject(mEvent, timeout); if (Result == WAIT_OBJECT_0) { retval = true; } else { CancelIo(mHandle); } ResetEvent(mEvent); } return retval; } #endif