1 #include "OISConfig.h" 2 #ifdef OIS_WIN32_WIIMOTE_SUPPORT 3 //cWiimote 0.2 by Kevin Forbes (http://simulatedcomicproduct.com) 4 //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. 5 //This was based in part on Alan Macek <www.alanmacek.com>'s USB interface library 6 7 //Edited for Toshiba Stack support (hopefully also all others) by 8 //Sean Stellingwerff (http://sean.stellingwerff.com) using information 9 //gathered from http://www.lvr.com/hidpage.htm (Thanks a million! :D) 10 11 //#include "stdafx.h" 12 #include "hiddevice.h" 13 14 extern "C" 15 { 16 #include "hidsdi.h" 17 #include <Setupapi.h> 18 } 19 #pragma comment(lib, "setupapi.lib") 20 #pragma comment(lib, "hid.lib") 21 22 HIDP_CAPS Capabilities; 23 PSP_DEVICE_INTERFACE_DETAIL_DATA detailData; 24 25 cHIDDevice::cHIDDevice() : mConnected(false), mHandle(NULL), mEvent(NULL) 26 { 27 } 28 29 30 cHIDDevice::~cHIDDevice() 31 { 32 if (mConnected) 33 { 34 Disconnect(); 35 } 36 } 37 38 bool cHIDDevice::Disconnect() 39 { 40 bool retval = false; 41 if (mConnected) 42 { 43 retval = (CloseHandle(mHandle) == TRUE && CloseHandle(mEvent) == TRUE); 44 45 mConnected = false; 46 } 47 48 return retval; 49 } 50 51 bool cHIDDevice::Connect(unsigned short device_id, unsigned short vendor_id, int index) 52 { 53 if (mConnected) 54 { 55 if (!Disconnect()) 56 { 57 return false; 58 } 59 } 60 61 // Find the wiimote(s) 62 //for (int i = 0; i <= index; i++) 63 OpenDevice( device_id, vendor_id, index ); 64 65 return mConnected; 66 } 67 68 bool cHIDDevice::OpenDevice(unsigned short device_id, unsigned short vendor_id, int index) 69 { 70 //Use a series of API calls to find a HID with a specified Vendor IF and Product ID. 71 HIDD_ATTRIBUTES Attributes; 72 SP_DEVICE_INTERFACE_DATA devInfoData; 73 bool LastDevice = FALSE; 74 bool MyDeviceDetected = FALSE; 75 int MemberIndex = 0; 76 int MembersFound = 0; 77 GUID HidGuid; 78 ULONG Length; 79 LONG Result; 80 HANDLE hDevInfo; 81 ULONG Required; 82 83 Length = 0; 84 detailData = NULL; 85 mHandle=NULL; 86 87 HidD_GetHidGuid(&HidGuid); 88 hDevInfo=SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); 89 90 devInfoData.cbSize = sizeof(devInfoData); 91 92 MemberIndex = 0; 93 MembersFound = 0; 94 LastDevice = FALSE; 95 96 do 97 { 98 Result=SetupDiEnumDeviceInterfaces(hDevInfo, 0, &HidGuid, MemberIndex, &devInfoData); 99 if (Result != 0) 100 { 101 Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, NULL, 0, &Length, NULL); 102 103 detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length); 104 detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 105 Result = SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, detailData, Length, &Required, NULL); 106 107 mHandle=CreateFile(detailData->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING, 0, NULL); 108 Attributes.Size = sizeof(Attributes); 109 110 Result = HidD_GetAttributes(mHandle, &Attributes); 111 //Is it the desired device? 112 113 MyDeviceDetected = FALSE; 114 115 if (Attributes.VendorID == vendor_id) 116 { 117 if (Attributes.ProductID == device_id) 118 { 119 if (MembersFound == index) 120 { 121 //Both the Vendor ID and Product ID match. 122 //printf("Wiimote found!\n"); 123 mConnected = true; 124 GetCapabilities(); 125 126 WriteHandle=CreateFile(detailData->DevicePath, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL); 127 MyDeviceDetected = TRUE; 128 129 PrepareForOverlappedTransfer(); 130 131 mEvent = CreateEvent(NULL, TRUE, TRUE, ""); 132 mOverlapped.Offset = 0; 133 mOverlapped.OffsetHigh = 0; 134 mOverlapped.hEvent = mEvent; 135 136 } else { 137 //The Product ID doesn't match. 138 CloseHandle(mHandle); 139 } 140 141 MembersFound++; 142 } 143 } else { 144 CloseHandle(mHandle); 145 } 146 free(detailData); 147 } else { 148 LastDevice=TRUE; 149 } 150 MemberIndex = MemberIndex + 1; 151 } while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE)); 152 153 SetupDiDestroyDeviceInfoList(hDevInfo); 154 return MyDeviceDetected; 155 } 156 157 bool cHIDDevice::WriteToDevice(unsigned const char * OutputReport, int num_bytes) 158 { 159 bool retval = false; 160 if (mConnected) 161 { 162 DWORD bytes_written; 163 retval = (WriteFile( WriteHandle, OutputReport, num_bytes, &bytes_written, &mOverlapped) == TRUE); 164 retval = retval && bytes_written == num_bytes; 165 } 166 return retval; 167 } 168 169 void cHIDDevice::PrepareForOverlappedTransfer() 170 { 171 //Get a handle to the device for the overlapped ReadFiles. 172 ReadHandle=CreateFile(detailData->DevicePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 173 } 174 175 void cHIDDevice::GetCapabilities() 176 { 177 //Get the Capabilities structure for the device. 178 PHIDP_PREPARSED_DATA PreparsedData; 179 HidD_GetPreparsedData(mHandle, &PreparsedData); 180 HidP_GetCaps(PreparsedData, &Capabilities); 181 182 //No need for PreparsedData any more, so free the memory it's using. 183 HidD_FreePreparsedData(PreparsedData); 184 } 185 186 bool cHIDDevice::ReadFromDevice(unsigned const char * buffer, int max_bytes, int & bytes_read, int timeout) 187 { 188 bool retval = false; 189 if (mConnected) 190 { 191 ReadFile( ReadHandle, (LPVOID)buffer,max_bytes,(LPDWORD)&bytes_read,(LPOVERLAPPED) &mOverlapped); 192 DWORD Result = WaitForSingleObject(mEvent, timeout); 193 if (Result == WAIT_OBJECT_0) 194 { 195 retval = true; 196 } 197 else 198 { 199 CancelIo(mHandle); 200 } 201 ResetEvent(mEvent); 202 } 203 return retval; 204 } 205 #endif 206