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