//-- AsyncBluetoothPairDeviceRequest State Machine ----- static bool AsyncBluetoothPairDeviceRequest__findBluetoothRadio(BluetoothPairDeviceState *state) { assert(state->isMainThread()); bool bSuccess= true; if (find_first_bluetooth_radio(&state->hRadio) && state->hRadio != INVALID_HANDLE_VALUE) { SERVER_LOG_INFO("AsyncBluetoothPairDeviceRequest") << "Found a bluetooth radio"; } else { SERVER_LOG_ERROR("AsyncBluetoothPairDeviceRequest") << "Failed to find a bluetooth radio"; bSuccess= false; } if (bSuccess) { DWORD result= BluetoothGetRadioInfo(state->hRadio, &state->radioInfo); if (result == ERROR_SUCCESS) { SERVER_LOG_INFO("AsyncBluetoothPairDeviceRequest") << "Retrieved radio info"; state->host_address_string= bluetooth_address_to_string(&state->radioInfo.address); } else { SERVER_LOG_ERROR("AsyncBluetoothPairDeviceRequest") << "Failed to retrieve radio info (Error Code: " << std::hex << std::setfill('0') << std::setw(8) << result; bSuccess= false; } } return bSuccess; }
void MorpheusHMD::close() { if (USBContext->sensor_device_handle != nullptr || USBContext->usb_device_handle != nullptr) { if (USBContext->sensor_device_handle != nullptr) { SERVER_LOG_INFO("MorpheusHMD::close") << "Closing MorpheusHMD sensor interface(" << USBContext->sensor_device_path << ")"; hid_close(USBContext->sensor_device_handle); } if (USBContext->usb_device_handle != nullptr) { SERVER_LOG_INFO("MorpheusHMD::close") << "Closing MorpheusHMD command interface"; morpheus_set_headset_power(USBContext, false); morpheus_close_usb_device(USBContext); } USBContext->Reset(); InData->Reset(); } else { SERVER_LOG_INFO("MorpheusHMD::close") << "MorpheusHMD already closed. Ignoring request."; } }
bool CContext::create_thread_pool(net::CListenManager<CListener>* listen_manager) { SERVER_LOG_INFO("Started to create waiter thread pool.\n"); if (_config->get_thread_number() < 1) { SERVER_LOG_ERROR("Server thread number is not specified.\n"); return false; } // 创建线程池 _thread_pool.create(_config->get_thread_number(), this); uint16_t thread_count = _thread_pool.get_thread_count(); CWorkThread** thread_array = _thread_pool.get_thread_array(); // 设置线程运行时参数 for (uint16_t i=0; i<thread_count; ++i) { uint16_t listen_count = listen_manager->get_listener_count(); CListener* listener_array = listen_manager->get_listener_array(); thread_array[i]->add_listener_array(listener_array, listen_count); } _thread_pool.activate(); SERVER_LOG_INFO("Created waiter thread pool success.\n"); return true; }
bool ServerDeviceView::poll() { bool bSuccessfullyUpdated= true; IDeviceInterface* device = getDevice(); // Only poll data from open, bluetooth controllers if (device != nullptr && device->getIsReadyToPoll()) { switch (device->poll()) { case IDeviceInterface::_PollResultSuccessNoData: { long max_failure= device->getMaxPollFailureCount(); ++m_pollNoDataCount; if (m_pollNoDataCount > max_failure) { SERVER_LOG_INFO("ServerDeviceView::poll") << "Device id " << getDeviceID() << " closing due to no data (" << max_failure << " failed poll attempts)"; device->close(); bSuccessfullyUpdated= false; } } break; case IDeviceInterface::_PollResultSuccessNewData: { m_pollNoDataCount= 0; m_lastNewDataTimestamp= std::chrono::high_resolution_clock::now(); // If we got new sensor data, then we have new state to publish markStateAsUnpublished(); bSuccessfullyUpdated= true; } break; case IDeviceInterface::_PollResultFailure: { SERVER_LOG_INFO("ServerDeviceView::poll") << "Device id " << getDeviceID() << " closing due to failed read"; device->close(); bSuccessfullyUpdated= false; } break; } } return bSuccessfullyUpdated; }
static bool AsyncBluetoothPairDeviceRequest__registerHostAddress( ServerControllerViewPtr &controllerView, BluetoothPairDeviceState *state) { assert(state->isMainThread()); const int controller_id= controllerView->getDeviceID(); bool bSuccess= true; if (controllerView->setHostBluetoothAddress(state->host_address_string)) { SERVER_LOG_INFO("AsyncBluetoothPairDeviceRequest") << "Assigned host address " << state->host_address_string << " to controller id " << controller_id; } else { SERVER_LOG_ERROR("AsyncBluetoothPairDeviceRequest") << "Failed to set host address " << state->host_address_string << " on controller id " << controller_id; bSuccess= false; } return bSuccess; }
void PSDualShock4Controller::close() { if (getIsOpen()) { SERVER_LOG_INFO("PSDualShock4Controller::close") << "Closing PSDualShock4Controller(" << HIDDetails.Device_path << ")"; if (HIDDetails.Handle != nullptr) { if (IsBluetooth) { clearAndWriteDataOut(); } hid_close(HIDDetails.Handle); HIDDetails.Handle = nullptr; } } else { SERVER_LOG_INFO("PSDualShock4Controller::close") << "PSDualShock4Controller(" << HIDDetails.Device_path << ") already closed. Ignoring request."; } }
//-- Queries ----- bool bluetooth_get_host_address(std::string &out_address) { bool bSuccess = true; HANDLE hRadio; if (find_first_bluetooth_radio(&hRadio) && hRadio != INVALID_HANDLE_VALUE) { SERVER_LOG_INFO("bluetooth_get_host_address") << "Found a bluetooth radio"; } else { SERVER_LOG_ERROR("bluetooth_get_host_address") << "Failed to find a bluetooth radio"; bSuccess = false; } if (bSuccess) { BLUETOOTH_RADIO_INFO radioInfo; memset(&radioInfo, 0, sizeof(BLUETOOTH_RADIO_INFO)); radioInfo.dwSize = sizeof(BLUETOOTH_RADIO_INFO); DWORD result = BluetoothGetRadioInfo(hRadio, &radioInfo); if (result == ERROR_SUCCESS) { SERVER_LOG_INFO("bluetooth_get_host_address") << "Retrieved radio info"; out_address = bluetooth_address_to_string(&radioInfo.address); } else { SERVER_LOG_ERROR("bluetooth_get_host_address") << "Failed to retrieve radio info (Error Code: " << std::hex << std::setfill('0') << std::setw(8) << result; bSuccess = false; } } return bSuccess; }
void PSNaviController::close() { if (getIsOpen()) { SERVER_LOG_INFO("PSNaviController::close") << "Closing PSNaviController(" << HIDDetails.Device_path << ")"; if (HIDDetails.Handle != nullptr) { hid_close(HIDDetails.Handle); HIDDetails.Handle= nullptr; } if (HIDDetails.Handle_addr != nullptr) { hid_close(HIDDetails.Handle_addr); HIDDetails.Handle_addr= nullptr; } } else { SERVER_LOG_INFO("PSNaviController::close") << "PSNaviController(" << HIDDetails.Device_path << ") already closed. Ignoring request."; } }
void CRoom::_GameStart() { SERVER_LOG_INFO( "GameStart," << Id() ); ChangeState( E_RoomState_InGame ); SG_ASSERT( m_PlayerCount == CHall::Instance().RoomPlayerCount() ); for( s32 i=0; i<m_PlayerCount; ++i ) { CPlayer *player = (CPlayer*)m_Players[i]; SG_ASSERT( player && player->IsReady() ); player->GameStart(); } }
bool CContext::IgnorePipeSignal() { // 忽略PIPE信号 if (SIG_ERR == signal(SIGPIPE, SIG_IGN)) { SERVER_LOG_FATAL("Can not ignore PIPE signal for %s.\n", strerror(errno)); return false; } else { SERVER_LOG_INFO("Ignore PIPE signal success.\n"); return true; } }
bool CContext::create_listen_manager() { SERVER_LOG_INFO("Started to create listen manager.\n"); const net::ip_port_pair_array_t& listen_parameter = _config->get_listen_parameter(); if (0 == listen_parameter.size()) { SERVER_LOG_ERROR("Listen parameters are not specified.\n"); return false; } for (net::ip_port_pair_array_t::size_type i=0; i<listen_parameter.size(); ++i) { _listen_manager.add(listen_parameter[i].first, listen_parameter[i].second); SERVER_LOG_INFO("Added listener %s:%d.\n" , listen_parameter[i].first.to_string().c_str() , listen_parameter[i].second); } _listen_manager.create(true); SERVER_LOG_INFO("Created listen manager success.\n"); return true; }
bool PS3EyeTracker::open(const DeviceEnumerator *enumerator) { const TrackerDeviceEnumerator *tracker_enumerator = static_cast<const TrackerDeviceEnumerator *>(enumerator); const char *cur_dev_path = tracker_enumerator->get_path(); bool bSuccess = false; if (getIsOpen()) { SERVER_LOG_WARNING("PS3EyeTracker::open") << "PS3EyeTracker(" << cur_dev_path << ") already open. Ignoring request."; bSuccess = true; } else { const int camera_index = tracker_enumerator->get_camera_index(); SERVER_LOG_INFO("PS3EyeTracker::open") << "Opening PS3EyeTracker(" << cur_dev_path << ", camera_index=" << camera_index << ")"; VideoCapture = new PSEyeVideoCapture(camera_index); if (VideoCapture->isOpened()) { CaptureData = new PSEyeCaptureData; USBDevicePath = enumerator->get_path(); bSuccess = true; } else { SERVER_LOG_ERROR("PS3EyeTracker::open") << "Failed to open PS3EyeTracker(" << cur_dev_path << ", camera_index=" << camera_index << ")"; close(); } } if (bSuccess) { std::string identifier = VideoCapture->getUniqueIndentifier(); std::string config_name = "PS3EyeTrackerConfig_"; config_name.append(identifier); cfg = PS3EyeTrackerConfig(config_name); cfg.load(); setExposure(cfg.exposure); setGain(cfg.gain); } return bSuccess; }
void CRoom::_GameEnd(CPlayer *loser) { SG_ASSERT( loser != NULL ); SERVER_LOG_INFO( "GameEnd," << Id() << "," << loser->UserId().c_str() ); ChangeState( E_RoomState_Wait ); SG_ASSERT( m_PlayerCount == CHall::Instance().RoomPlayerCount() ); for( s32 i=0; i<m_PlayerCount; ++i ) { CPlayer *player = (CPlayer*)m_Players[i]; SG_ASSERT( player ); player->GameEnd(); } }
bool MorpheusHMD::open( const DeviceEnumerator *enumerator) { const HMDDeviceEnumerator *pEnum = static_cast<const HMDDeviceEnumerator *>(enumerator); const char *cur_dev_path = pEnum->get_path(); bool success = false; if (getIsOpen()) { SERVER_LOG_WARNING("MorpheusHMD::open") << "MorpheusHMD(" << cur_dev_path << ") already open. Ignoring request."; success = true; } else { SERVER_LOG_INFO("MorpheusHMD::open") << "Opening MorpheusHMD(" << cur_dev_path << ")."; USBContext->device_identifier = cur_dev_path; // Open the sensor interface using HIDAPI USBContext->sensor_device_path = pEnum->get_hid_hmd_enumerator()->get_interface_path(MORPHEUS_SENSOR_INTERFACE); USBContext->sensor_device_handle = hid_open_path(USBContext->sensor_device_path.c_str()); if (USBContext->sensor_device_handle != nullptr) { hid_set_nonblocking(USBContext->sensor_device_handle, 1); } // Open the command interface using libusb. // NOTE: Ideally we would use one usb library for both interfaces, but there are some complications. // A) The command interface uses the bulk transfer endpoint and HIDApi doesn't support that endpoint. // B) In Windows, libusb doesn't handle a high frequency of requests coming from two different threads well. // In this case, PS3EyeDriver is constantly sending bulk transfer requests in its own thread to get video frames. // If we started sending control transfer requests for the sensor data in the main thread at the same time // it can lead to a crash. It shouldn't, but this was a problem previously setting video feed properties // from the color config tool while a video feed was running. if (!cfg.disable_command_interface) { morpheus_open_usb_device(USBContext); } else { SERVER_LOG_WARNING("MorpheusHMD::open") << "Morpheus command interface is flagged as DISABLED."; } if (getIsOpen()) // Controller was opened and has an index { if (USBContext->usb_device_handle != nullptr) { if (morpheus_set_headset_power(USBContext, true)) { if (morpheus_enable_tracking(USBContext)) { morpheus_set_led_brightness(USBContext, _MorpheusLED_ALL, 0); } } } // Always save the config back out in case some defaults changed cfg.save(); // Reset the polling sequence counter NextPollSequenceNumber = 0; success = true; } else { SERVER_LOG_ERROR("MorpheusHMD::open") << "Failed to open MorpheusHMD(" << cur_dev_path << ")"; close(); } } return success; }
bool DeviceTypeManager::update_connected_devices() { bool success = false; // Don't do any connection opening/closing until all pending bluetooth operations are finished if (can_update_connected_devices()) { const int maxDeviceCount = getMaxDevices(); ServerDeviceViewPtr *temp_device_list = new ServerDeviceViewPtr[maxDeviceCount]; bool bSendControllerUpdatedNotification = false; // Step 1 // See if any devices shuffled order OR if any new controllers were attached. // Migrate open devices to a new temp list in the order // that they appear in the device enumerator. { DeviceEnumerator *enumerator = allocate_device_enumerator(); while (enumerator->is_valid()) { // Find device index for the device with the matching device path int device_id = find_open_device_device_id(enumerator); // Existing device case (Most common) if (device_id != -1) { // Fetch the device from it's existing device slot ServerDeviceViewPtr existingDevice = getDeviceViewPtr(device_id); // Move it to the same slot in the temp list temp_device_list[device_id] = existingDevice; // Remove it from the previous list m_deviceViews[device_id] = ServerDeviceViewPtr(); } // New controller connected case else { int device_id = find_first_closed_device_device_id(); if (device_id != -1) { // Fetch the controller from it's existing controller slot ServerDeviceViewPtr existingDevice = getDeviceViewPtr(device_id); // Move it to the available slot existingDevice->setDeviceID(static_cast<int>(device_id)); temp_device_list[device_id] = existingDevice; // Remove it from the previous list m_deviceViews[device_id] = ServerDeviceViewPtr(); // Attempt to open the device if (existingDevice->open(enumerator)) { const char *device_type_name = CommonDeviceState::getDeviceTypeString(existingDevice->getDevice()->getDeviceType()); SERVER_LOG_INFO("DeviceTypeManager::update_connected_devices") << "Device device_id " << device_id << " (" << device_type_name << ") connected"; bSendControllerUpdatedNotification = true; } } else { SERVER_LOG_ERROR("DeviceTypeManager::update_connected_devices") << "Can't connect any more new devices. Too many open device."; break; } } enumerator->next(); } free_device_enumerator(enumerator); } // Step 2 // Close any remaining open controllers not listed in the device enumerator. // Copy over any closed controllers to the temp. for (int existing_device_id = 0; existing_device_id < maxDeviceCount; ++existing_device_id) { ServerDeviceViewPtr existingDevice = getDeviceViewPtr(existing_device_id); if (existingDevice) { // Any "open" controllers remaining in the old list need to be closed // since they no longer appear in the connected device list. // This probably shouldn't happen very often (at all?) as polling should catch // disconnected controllers first. if (existingDevice->getIsOpen()) { const char *device_type_name = CommonDeviceState::getDeviceTypeString(existingDevice->getDevice()->getDeviceType()); SERVER_LOG_WARNING("DeviceTypeManager::update_connected_devices") << "Closing device " << existing_device_id << " (" << device_type_name << ") since it's no longer in the device list."; existingDevice->close(); bSendControllerUpdatedNotification = true; } // Move it to the temp slot temp_device_list[existing_device_id] = existingDevice; // Remove it from the previous list m_deviceViews[existing_device_id] = ServerDeviceViewPtr(); } } // Step 3 // Copy the temp controller list back over top the original list for (int device_id = 0; device_id < maxDeviceCount; ++device_id) { m_deviceViews[device_id] = temp_device_list[device_id]; } if (bSendControllerUpdatedNotification) { send_device_list_changed_notification(); } delete[] temp_device_list; success = true; } return success; }
bool PSNaviController::open( const DeviceEnumerator *enumerator) { const ControllerDeviceEnumerator *pEnum = static_cast<const ControllerDeviceEnumerator *>(enumerator); const char *cur_dev_path= pEnum->get_path(); bool success= false; if (getIsOpen()) { SERVER_LOG_WARNING("PSNaviController::open") << "PSNavoController(" << cur_dev_path << ") already open. Ignoring request."; success= true; } else { char cur_dev_serial_number[256]; SERVER_LOG_INFO("PSNaviController::open") << "Opening PSNaviController(" << cur_dev_path << ")"; if (pEnum->get_serial_number(cur_dev_serial_number, sizeof(cur_dev_serial_number))) { SERVER_LOG_INFO("PSNaviController::open") << " with serial_number: " << cur_dev_serial_number; } else { cur_dev_serial_number[0]= '\0'; SERVER_LOG_INFO("PSNaviController::open") << " with EMPTY serial_number"; } HIDDetails.Device_path = cur_dev_path; #ifdef _WIN32 HIDDetails.Device_path_addr = HIDDetails.Device_path; HIDDetails.Device_path_addr.replace(HIDDetails.Device_path_addr.find("&col01#"), 7, "&col02#"); HIDDetails.Device_path_addr.replace(HIDDetails.Device_path_addr.find("&0000#"), 6, "&0001#"); HIDDetails.Handle_addr = hid_open_path(HIDDetails.Device_path_addr.c_str()); hid_set_nonblocking(HIDDetails.Handle_addr, 1); #endif HIDDetails.Handle = hid_open_path(HIDDetails.Device_path.c_str()); hid_set_nonblocking(HIDDetails.Handle, 1); IsBluetooth = (strlen(cur_dev_serial_number) > 0); if (getIsOpen()) // Controller was opened and has an index { // Get the bluetooth address #ifndef _WIN32 // On my Mac, getting the bt feature report when connected via // bt crashes the controller. So we simply copy the serial number. // It gets modified in getBTAddress. // TODO: Copy this over anyway even in Windows. Check getBTAddress // comments for handling windows serial_number. // Once done, we can remove the ifndef above. std::string mbs(cur_dev_serial_number); HIDDetails.Bt_addr = mbs; #endif if (getBTAddress(HIDDetails.Host_bt_addr, HIDDetails.Bt_addr)) { // Load the config file std::string btaddr = HIDDetails.Bt_addr; std::replace(btaddr.begin(), btaddr.end(), ':', '_'); cfg = PSNaviControllerConfig(btaddr); cfg.load(); // TODO: Other startup. success= true; } else { // If serial is still bad, maybe we have a disconnected // controller still showing up in hidapi SERVER_LOG_ERROR("PSNaviController::open") << "Failed to get bluetooth address of PSNaviController(" << cur_dev_path << ")"; success= false; } // Reset the polling sequence counter NextPollSequenceNumber= 0; } else { SERVER_LOG_ERROR("PSNaviController::open") << "Failed to open PSNaviController(" << cur_dev_path << ")"; success= false; } } return success; }
bool AsyncBluetoothPairDeviceRequest::start() { bool success= true; const int controller_id= m_controllerView->getDeviceID(); // Reset the pairing device state BluetoothPairDeviceState *state= reinterpret_cast<BluetoothPairDeviceState *>(m_internal_state); state->initialize(controller_id); state->controller_serial_string= m_controllerView->getSerial(); state->controller_device_type= m_controllerView->getControllerDeviceType(); // Make sure the controller we're working with is a USB connection if (success && m_controllerView->getIsOpen() && m_controllerView->getIsBluetooth()) { SERVER_LOG_ERROR("AsyncBluetoothPairDeviceRequest") << "Controller " << controller_id << " isn't an open USB device"; success= false; } // Find the bluetooth address of the host adapter if (success) { success= AsyncBluetoothPairDeviceRequest__findBluetoothRadio(state); } // Make sure the controller isn't already paired with this host adapter if (m_controllerView->getAssignedHostBluetoothAddress() != state->host_address_string) { // Assign this host address on the controller. // NOTE: This needs to be done on the main thread since the controller view isn't thread safe. if (success) { success= AsyncBluetoothPairDeviceRequest__registerHostAddress(m_controllerView, state); } // Kick off the worker thread to do the rest of the work if (success) { state->worker_thread_handle= CreateThread( NULL, // default security attributes 0, // use default stack size AsyncBluetoothPairDeviceThreadFunction, // thread function pointer m_internal_state, // argument to thread function 0, // use default creation flags NULL); // returns the thread identifier if (state->worker_thread_handle == NULL) { SERVER_LOG_ERROR("AsyncBluetoothPairDeviceRequest") << "Failed to start worker thread!"; success= false; } } if (success) { m_status = AsyncBluetoothRequest::running; } } else { SERVER_LOG_INFO("AsyncBluetoothPairDeviceRequest") << "Controller already paired"; m_status= AsyncBluetoothRequest::succeeded; } if (!success) { m_status = AsyncBluetoothRequest::failed; } return success; }
bool PSDualShock4Controller::open( const DeviceEnumerator *enumerator) { const ControllerDeviceEnumerator *pEnum = static_cast<const ControllerDeviceEnumerator *>(enumerator); const char *cur_dev_path = pEnum->get_path(); bool success = false; if (getIsOpen()) { SERVER_LOG_WARNING("PSDualShock4Controller::open") << "PSDualShock4Controller(" << cur_dev_path << ") already open. Ignoring request."; success = true; } else { char cur_dev_serial_number[256]; SERVER_LOG_INFO("PSDualShock4Controller::open") << "Opening PSDualShock4Controller(" << cur_dev_path << ")"; if (pEnum->get_serial_number(cur_dev_serial_number, sizeof(cur_dev_serial_number))) { SERVER_LOG_INFO("PSDualShock4Controller::open") << " with serial_number: " << cur_dev_serial_number; } else { cur_dev_serial_number[0] = '\0'; SERVER_LOG_INFO("PSDualShock4Controller::open") << " with EMPTY serial_number"; } // Attempt to open the controller HIDDetails.vendor_id = pEnum->get_vendor_id(); HIDDetails.product_id = pEnum->get_product_id(); HIDDetails.Device_path = cur_dev_path; HIDDetails.Handle = hid_open_path(HIDDetails.Device_path.c_str()); if (HIDDetails.Handle != nullptr) // Controller was opened and has an index { // Don't block on hid report requests hid_set_nonblocking(HIDDetails.Handle, 1); /* -USB or Bluetooth Device- On my Mac, using bluetooth, cur_dev->path = Bluetooth_054c_03d5_779732e8 cur_dev->serial_number = 00-06-f7-97-32-e8 On my Mac, using USB, cur_dev->path = USB_054c_03d5_14100000 cur_dev->serial_number = "" (not null, just empty) On my Windows 10 box (different controller), using bluetooth cur_dev->path = \\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002054c_pid&05c4#8&217a4584&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} cur_dev->serial_number = 1c666d2c8deb Using USB cur_dev->path = \\?\hid#vid_054c&pid_03d5&col01#6&7773e57&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} cur_dev->serial_number = (null) */ // Bluetooth connected if (strlen(cur_dev_serial_number) > 0) { IsBluetooth = true; // Convert the serial number into a normalized bluetooth address of the form: "xx:xx:xx:xx:xx:xx" char szNormalizedControllerAddress[18]; ServerUtility::bluetooth_cstr_address_normalize( cur_dev_serial_number, true, ':', szNormalizedControllerAddress, sizeof(szNormalizedControllerAddress)); // Save the controller address as a std::string HIDDetails.Bt_addr = std::string(szNormalizedControllerAddress); // Get the (possibly cached) bluetooth address of the first bluetooth adapter if (!bluetooth_get_host_address(HIDDetails.Host_bt_addr)) { HIDDetails.Host_bt_addr= "00:00:00:00:00:00"; } success = true; } // USB Connected else { IsBluetooth = false; // Fetch the bluetooth host and controller addresses via USB HID report request success = getBTAddressesViaUSB(HIDDetails.Host_bt_addr, HIDDetails.Bt_addr); if (!success) { // If serial is still bad, maybe we have a disconnected // controller still showing up in hidapi SERVER_LOG_ERROR("PSDualShock4Controller::open") << "Failed to get bluetooth address of PSDualShock4Controller(" << cur_dev_path << ")"; } } if (success) { // Build a unique name for the config file using bluetooth address of the controller char szConfigSuffix[18]; ServerUtility::bluetooth_cstr_address_normalize( HIDDetails.Bt_addr.c_str(), true, '_', szConfigSuffix, sizeof(szConfigSuffix)); std::string config_name("dualshock4_"); config_name += szConfigSuffix; // Load the config file cfg = PSDualShock4ControllerConfig(config_name); cfg.load(); // Save it back out again in case any defaults changed cfg.save(); } // Reset the polling sequence counter NextPollSequenceNumber = 0; // Write out the initial controller state if (success && IsBluetooth) { bWriteStateDirty= true; writeDataOut(); } } else { SERVER_LOG_ERROR("PSDualShock4Controller::open") << "Failed to open PSDualShock4Controller(" << cur_dev_path << ")"; success = false; } } return success; }