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 
cHIDDevice()25 cHIDDevice::cHIDDevice() : mConnected(false), mHandle(NULL), mEvent(NULL)
26 {
27 }
28 
29 
~cHIDDevice()30 cHIDDevice::~cHIDDevice()
31 {
32 	if (mConnected)
33 	{
34 		Disconnect();
35 	}
36 }
37 
Disconnect()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 
Connect(unsigned short device_id,unsigned short vendor_id,int index)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 
OpenDevice(unsigned short device_id,unsigned short vendor_id,int index)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 
WriteToDevice(unsigned const char * OutputReport,int num_bytes)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 
PrepareForOverlappedTransfer()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 
GetCapabilities()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 
ReadFromDevice(unsigned const char * buffer,int max_bytes,int & bytes_read,int timeout)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