Home | History | Annotate | Download | only in WiiMote
      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