Example #1
0
// Connect to a Wiimote with a known device path.
bool WiimoteWindows::ConnectInternal()
{
  if (IsConnected())
    return true;

  if (!IsNewWiimote(UTF16ToUTF8(m_devicepath)))
    return false;

  auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;

  m_dev_handle = CreateFile(m_devicepath.c_str(), GENERIC_READ | GENERIC_WRITE, open_flags, nullptr,
                            OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);

  if (m_dev_handle == INVALID_HANDLE_VALUE)
  {
    m_dev_handle = nullptr;
    return false;
  }

#if 0
	TCHAR name[128] = {};
	pHidD_GetProductString(dev_handle, name, 128);

	//ERROR_LOG(WIIMOTE, "Product string: %s", TStrToUTF8(name).c_str());

	if (!IsValidBluetoothName(TStrToUTF8(name)))
	{
		CloseHandle(dev_handle);
		dev_handle = 0;
		return false;
	}
#endif

#if 0
	HIDD_ATTRIBUTES attr;
	attr.Size = sizeof(attr);
	if (!pHidD_GetAttributes(dev_handle, &attr))
	{
		CloseHandle(dev_handle);
		dev_handle = 0;
		return false;
	}
#endif

  // TODO: thread isn't started here now, do this elsewhere
  // This isn't as drastic as it sounds, since the process in which the threads
  // reside is normal priority. Needed for keeping audio reports at a decent rate
  /*
    if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL))
    {
      ERROR_LOG(WIIMOTE, "Failed to set Wiimote thread priority");
    }
  */

  return true;
}
Example #2
0
// Connect to a Wiimote with a known device path.
bool WiimoteWindows::ConnectInternal()
{
	if (IsConnected())
		return false;

#ifdef SHARE_WRITE_WIIMOTES
	std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
	if (g_connected_wiimotes.count(m_devicepath) != 0)
		return false;

	auto const open_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;
#else
	// Having no FILE_SHARE_WRITE disallows us from connecting to the same Wiimote twice.
	// (And disallows using Wiimotes in use by other programs)
	// This is what "WiiYourself" does.
	// Apparently this doesn't work for everyone. It might be their fault.
	auto const open_flags = FILE_SHARE_READ;
#endif

	m_dev_handle = CreateFile(m_devicepath.c_str(),
		GENERIC_READ | GENERIC_WRITE, open_flags,
		nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);

	if (m_dev_handle == INVALID_HANDLE_VALUE)
	{
		m_dev_handle = 0;
		return false;
	}

#if 0
	TCHAR name[128] = {};
	pHidD_GetProductString(dev_handle, name, 128);

	//ERROR_LOG(WIIMOTE, "Product string: %s", TStrToUTF8(name).c_str());

	if (!IsValidBluetoothName(TStrToUTF8(name)))
	{
		CloseHandle(dev_handle);
		dev_handle = 0;
		return false;
	}
#endif

#if 0
	HIDD_ATTRIBUTES attr;
	attr.Size = sizeof(attr);
	if (!pHidD_GetAttributes(dev_handle, &attr))
	{
		CloseHandle(dev_handle);
		dev_handle = 0;
		return false;
	}
#endif

	// TODO: thread isn't started here now, do this elsewhere
	// This isn't as drastic as it sounds, since the process in which the threads
	// reside is normal priority. Needed for keeping audio reports at a decent rate
/*
	if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL))
	{
		ERROR_LOG(WIIMOTE, "Failed to set Wiimote thread priority");
	}
*/
#ifdef SHARE_WRITE_WIIMOTES
	g_connected_wiimotes.insert(m_devicepath);
#endif

	return true;
}
Example #3
0
// A convoluted way of checking if a device is a Wii Balance Board and if it is a connectible Wiimote.
// Because nothing on Windows should be easy.
// (We can't seem to easily identify the Bluetooth device an HID device belongs to...)
void WiimoteScanner::CheckDeviceType(std::basic_string<TCHAR> &devicepath, bool &real_wiimote, bool &is_bb)
{
	real_wiimote = false;
	is_bb = false;

#ifdef SHARE_WRITE_WIIMOTES
	std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
	if (g_connected_wiimotes.count(devicepath) != 0)
		return;
#endif

	HANDLE dev_handle = CreateFile(devicepath.c_str(),
	                               GENERIC_READ | GENERIC_WRITE,
	                               FILE_SHARE_READ | FILE_SHARE_WRITE,
	                               nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
	                               nullptr);
	if (dev_handle == INVALID_HANDLE_VALUE)
		return;
	// enable to only check for official nintendo wiimotes/bb's
	bool check_vidpid = false;
	HIDD_ATTRIBUTES attrib;
	attrib.Size = sizeof(attrib);
	if (!check_vidpid ||
		(pHidD_GetAttributes(dev_handle, &attrib) &&
		(attrib.VendorID == 0x057e) &&
		(attrib.ProductID == 0x0306)))
	{
		// max_cycles insures we are never stuck here due to bad coding...
		int max_cycles = 20;
		u8 buf[MAX_PAYLOAD] = {0};

		u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
		// The new way to initialize the extension is by writing 0x55 to 0x(4)A400F0, then writing 0x00 to 0x(4)A400FB
		// 52 16 04 A4 00 F0 01 55
		// 52 16 04 A4 00 FB 01 00
		u8 const disable_enc_pt1_report[MAX_PAYLOAD] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_WRITE_DATA, 0x04, 0xa4, 0x00, 0xf0, 0x01, 0x55};
		u8 const disable_enc_pt2_report[MAX_PAYLOAD] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_WRITE_DATA, 0x04, 0xa4, 0x00, 0xfb, 0x01, 0x00};

		CheckDeviceType_Write(dev_handle,
		                      disable_enc_pt1_report,
		                      sizeof(disable_enc_pt1_report),
		                      1);
		CheckDeviceType_Write(dev_handle,
		                      disable_enc_pt2_report,
		                      sizeof(disable_enc_pt2_report),
		                      1);

		int rc = CheckDeviceType_Write(dev_handle,
		                               req_status_report,
		                               sizeof(req_status_report),
		                               1);

		while (rc > 0 && --max_cycles > 0)
		{
			if ((rc = CheckDeviceType_Read(dev_handle, buf, 1)) <= 0)
			{
				// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Read failed...");
				break;
			}

			switch (buf[1])
			{
				case WM_STATUS_REPORT:
				{
					real_wiimote = true;

					// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Status Report");
					wm_status_report * wsr = (wm_status_report*)&buf[2];
					if (wsr->extension)
					{
						// Wiimote with extension, we ask it what kind.
						u8 read_ext[MAX_PAYLOAD] = {0};
						read_ext[0] = WM_SET_REPORT | WM_BT_OUTPUT;
						read_ext[1] = WM_READ_DATA;
						// Extension type register.
						*(u32*)&read_ext[2] = Common::swap32(0x4a400fa);
						// Size.
						*(u16*)&read_ext[6] = Common::swap16(6);
						rc = CheckDeviceType_Write(dev_handle, read_ext, 8, 1);
					}
					else
					{
						// Normal Wiimote, exit while and be happy.
						rc = -1;
					}
					break;
				}
				case WM_ACK_DATA:
				{
					real_wiimote = true;
					//wm_acknowledge * wm = (wm_acknowledge*)&buf[2];
					//DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Ack Error: %X ReportID: %X", wm->errorID, wm->reportID);
					break;
				}
				case WM_READ_DATA_REPLY:
				{
					// DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Data Reply");
					wm_read_data_reply * wrdr
						= (wm_read_data_reply*)&buf[2];
					// Check if it has returned what we asked.
					if (Common::swap16(wrdr->address) == 0x00fa)
					{
						real_wiimote = true;
						// 0x020420A40000ULL means balance board.
						u64 ext_type = (*(u64*)&wrdr->data[0]);
						// DEBUG_LOG(WIIMOTE,
						//           "CheckDeviceType: GOT EXT TYPE %llX",
						//           ext_type);
						is_bb = (ext_type == 0x020420A40000ULL);
					}
					else
					{
						ERROR_LOG(WIIMOTE,
						          "CheckDeviceType: GOT UNREQUESTED ADDRESS %X",
						          Common::swap16(wrdr->address));
					}
					// force end
					rc = -1;

					break;
				}
				default:
				{
					// We let read try again incase there is another packet waiting.
					// DEBUG_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]);
					break;
				}
			}
		}
	}
	CloseHandle(dev_handle);
}