/// <summary>
/// Connect to a Wiimote paired to the PC via Bluetooth
/// </summary>
public void Connect()
{
int index = 0;
bool found = false;
Guid guid;
// get the GUID of the HID class
HIDImports.HidD_GetHidGuid(out guid);
// get a handle to all devices that are part of the HID class
// Fun fact: DIGCF_PRESENT worked on my machine just fine. I reinstalled Vista, and now it no longer finds the Wiimote with that parameter enabled...
IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE); // | HIDImports.DIGCF_PRESENT);
// create a new interface data struct and initialize its size
HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
diData.cbSize = Marshal.SizeOf(diData);
// get a device interface to a single device (enumerate all devices)
while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index, ref diData))
{
UInt32 size;
// get the buffer size for this device detail instance (returned in the size parameter)
HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
// create a detail struct and set its size
HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
// yeah, yeah...well, see, on Win x86, cbSize must be 5 for some reason. On x64, apparently 8 is what it wants.
// someday I should figure this out. Thanks to Paul Miller on this...
if (IntPtr.Size == 8)
{
diDetail.cbSize = 8;
}
else
{
diDetail.cbSize = 5;
}
// actually get the detail struct
if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
{
Debug.WriteLine(index + " " + diDetail.DevicePath + " " + Marshal.GetLastWin32Error());
// open a read/write handle to our device using the DevicePath returned
mHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);
// create an attributes struct and initialize the size
HIDImports.HIDD_ATTRIBUTES attrib = new HIDImports.HIDD_ATTRIBUTES();
attrib.Size = Marshal.SizeOf(attrib);
// get the attributes of the current device
if (HIDImports.HidD_GetAttributes(mHandle.DangerousGetHandle(), ref attrib))
{
// if the vendor and product IDs match up
if (attrib.VendorID == VID && attrib.ProductID == PID)
{
if (!IsRemoteConnected((int)index))
{
Debug.WriteLine("Found it!");
found = true;
remoteID = (int)index;
connectedRemoteIDs.Add(remoteID);
}
// create a nice .NET FileStream wrapping the handle above
mStream = new FileStream(mHandle, FileAccess.ReadWrite, REPORT_LENGTH, true);
// start an async read operation on it
BeginAsyncRead();
// read the calibration info from the controller
try
{
ReadCalibration();
}
catch
{
// if we fail above, try the alternate HID writes
mAltWriteMethod = true;
ReadCalibration();
}
// force a status check to get the state of any extensions plugged in at startup
GetStatus();
break;
}
else
{
// otherwise this isn't the controller, so close up the file handle
mHandle.Close();
}
}
}
else
{
// failed to get the detail struct
throw new Exception("SetupDiGetDeviceInterfaceDetail failed on index " + index);
}
// move to the next device
index++;
}
// clean up our list
HIDImports.SetupDiDestroyDeviceInfoList(hDevInfo);
// if we didn't find a Wiimote, throw an exception
if (!found)
{
throw new Exception("Wiimote not found in HID device list.");
}
}