// found in the LICENSE file.
#include "tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h"
+
+#include <autoinput.h>
#include <string.h>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
const Gamepad& input,
Gamepad* mapped) {
*mapped = input;
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ if (fabs(input.axes[2] + 1.0) <= 0.000001 &&
+ fabs(input.axes[5] + 1.0) <= 0.000001) {
+ // Left Trigger & Right Trigger are Buttons not ABS Value
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[7];
+ } else {
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ }
mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[12];
mapped->buttons[BUTTON_INDEX_START] = input.buttons[13];
mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
GamepadPlatformDataFetcherTizenTV::GamepadPlatformDataFetcherTizenTV() {
gamepad_manager_ = nullptr;
if (Gamepad_Create()) {
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ // initialize autoinput
+ VirtualKey_Initialize("gamepad-service");
+#endif
Initialize();
} else {
LOG(ERROR) << "[Gamepad_LOG] "
GamepadPlatformDataFetcherTizenTV::~GamepadPlatformDataFetcherTizenTV() {
CHECK(gamepad_manager_ != nullptr);
gamepad_manager_->UnregisterCallback(this);
-
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ vconf_ignore_key_changed(VCONF_GAMEHOME_STATUS,
+ GameHomeAPPStatusChangeCallback);
+#endif
// Need set gamepad_items_ to null before Gamepad_Destroy, caused by business
// logic
for (size_t i = 0; i < Gamepads::kItemsLengthCap; i++) {
}
}
Gamepad_Destroy();
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ // finalize autoinput module
+ VirtualKey_Finalize();
+#endif
}
void GamepadPlatformDataFetcherTizenTV::Initialize() {
InitTizenDevice();
EnumerateTizenDevices();
gamepad_manager_->RegisterCallback(this);
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ // added for homekey long press
+ if (-1 == vconf_notify_key_changed(VCONF_GAMEHOME_STATUS,
+ GameHomeAPPStatusChangeCallback, this)) {
+ LOG(ERROR) << "RegisterGamehomeStatusCallback Err";
+ }
+#endif
}
void GamepadPlatformDataFetcherTizenTV::InitTizenDevice() {
}
}
}
-
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+void GamepadPlatformDataFetcherTizenTV::GameHomeAPPStatusChangeCallback(
+ keynode_t* key,
+ void* data) {
+ LOG(INFO) << " Got GameHomeAPPStatusChangeCallback";
+ if (data == nullptr)
+ return;
+ GamepadPlatformDataFetcherTizenTV* instance =
+ (GamepadPlatformDataFetcherTizenTV*)data;
+ for (size_t i = 0; i < Gamepads::kItemsLengthCap; i++) {
+ if (instance->gamepad_items_[i] != nullptr) {
+ instance->gamepad_items_[i]->UpdateGameHomeAppStatus(key);
+ }
+ }
+}
+#endif
void GamepadPlatformDataFetcherTizenTV::GetGamepadData(
bool devices_changed_hint) {
TRACE_EVENT0("GAMEPAD", "GetGamepadData");
sType = " DISCONNECT ";
LOG(INFO) << sType << " pparam1 " << reinterpret_cast<char*>(pparam1);
-
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ strncpy(dev_info.UID, (char*)pparam1, OCI_SIZE_ID - 1);
+ strncpy(dev_info.name, (char*)pparam2, OCI_SIZE_NAME - 1);
+ LOG(INFO) << sType << " dev_info.UID " << dev_info.UID << " dev_info.name "
+ << dev_info.name;
+#else
if (t_GetDevManagerEventData(evType, dev_info,
reinterpret_cast<char*>(pparam1)) != OCI_OK) {
LOG(ERROR) << "[Gamepad_LOG] "
<< sType << "error != OCI_DEVICE_JOYSTICK ";
return;
}
+#endif
switch (type) {
case OCI_EVENT_DEV_CONNECT: {
// found in the LICENSE file.
#include "tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.h"
+#include <autoinput.h>
#include <utility>
#include "base/logging.h"
+#include "tizen_src/chromium_impl/build/tizen_version.h"
+#define VIRTUAL_KEY_GAMEHOME 572
namespace device {
"gamepad_ == nullptr return";
return false;
}
-
+#if TIZEN_VERSION_AT_LEAST(7, 0, 0)
+ // Check whether gamepad support such key
+ GamepadKey gamepad_key_list[1];
+ gamepad_key_list[0].type = OCI_EV_ABS;
+ gamepad_key_list[0].code = code;
+ int* support_result = NULL;
+ bool ret = false;
+ do {
+ if (gamepad_->HaveKeys(gamepad_key_list, 1, &support_result) != OCI_OK) {
+ LOG(ERROR) << "Call[HaveKeys]err";
+ break;
+ }
+ if (!support_result[0]) {
+ LOG(ERROR)
+ << "key[%d] is not supported. Set [baseline=0.0][range=32767.0]";
+ *baseline = 0.0;
+ *range = 32767.0;
+ ret = true;
+ break;
+ }
+ // Do not need to modify, because GetABSValueRange(int, long&, long&) used
+ // by accessory.
+ long min = 0l; // NOLINT(runtime/int)
+ long max = 0l; // NOLINT(runtime/int)
+ if (gamepad_->GetABSValueRange(code, max, min) == OCI_OK) {
+ (*baseline) = (min + max) / 2.0;
+ (*range) = (max - min) / 2.0;
+ ret = true;
+ break;
+ } else {
+ LOG(ERROR) << "[Gamepad_LOG] OCIGamepadItem::InitAxisRangeTizen(int "
+ "code, float* range) init error, code = "
+ << code;
+ }
+ } while (0);
+ free(support_result);
+ return ret;
+#else
// Do not need to modify, because GetABSValueRange(int, long&, long&) used by
// accessory.
long min = 0l; // NOLINT(runtime/int)
<< code;
return false;
}
+#endif
}
bool OCIGamepadItem::InitAxisRangeTizen() {
range_tizen_trigger_range_ = 0.0;
s_oci_gamepaditem_num_++;
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ if (vconf_get_int(VCONF_GAMEHOME_STATUS, &home_key_long_press_setting_)) {
+ LOG(ERROR) << "Get GamehomeStatus Err";
+ }
+ home_key_long_press_status_ = LongPressStatus::kNone;
+ home_event_.code = OCI_BTN_15;
+ home_event_.type = OCI_EV_KEY;
+ home_event_.value = (long)HomekeyValue::kNoEvent;
+#endif
}
OCIGamepadItem::~OCIGamepadItem() {
<< "[Gamepad_LOG] OCIGamepadItem::Create() gamepad_ == nullptr return";
return false;
}
-
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ // handle homekey seperately.
+ LOG(ERROR) << "[Gamepad_LOG] RegisterKeyHandler";
+ gamepad_->RegisterKeyHandler(OCI_BTN_15, OCI_EV_KEY, GamepadHomekeyCallback,
+ this);
+#endif
CHECK(pad_ != nullptr);
pad_->connected = true;
pad_->vibration_actuator.not_null = gamepad_->IsForceFeedbackSupported();
CHECK(manager_ != nullptr);
CHECK(gamepad_ != nullptr);
CHECK(pad_ != nullptr);
-
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ gamepad_->UnRegisterKeyHandler(OCI_BTN_15, OCI_EV_KEY,
+ GamepadHomekeyCallback);
+#endif
manager_->DestroyDevice(gamepad_->GetID());
gamepad_ = nullptr;
pad_->connected = false;
return;
}
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+// No Need
+#else
void OCIGamepadItem::t_OnCallback(int type,
void* pparam1,
void* pparam2,
void* pparam3) {
// used by parent class
}
+#endif
const char* OCIGamepadItem::GetUID() {
LOG(INFO) << "GamePad " << info_.UID;
}
void OCIGamepadItem::RefreshOCIGamepadDataEachEvent(
- const OCIControllerEvent& event,
- const int index) {
+ const OCIControllerEvent& event) {
Gamepad& pad = (*pad_);
size_t item = event.code;
if (event.type == OCI_EV_ABS) {
pad.buttons_length = item + 1;
}
}
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ /*for home key long press, we should use
+ * pad.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds()
+ * + event.time - current_microseconds;
+ * instead of
+ * pad.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
+ * to make APP get home key's pressing hold time.
+ * for example, user press Home key for 500ms,
+ * APP could get the "home key pressing time" =
+ * "release time" - "press time" = 500ms.
+ * If using "pad.timestamp =
+ * GamepadDataFetcher::CurrentTimeInMicroseconds()",
+ * APP will get the "home
+ * key pressing time" = "release time" - "press time" = 3ms.
+ * (poll thread interval time)
+ * */
+ struct timeval current_time;
+ gettimeofday(¤t_time, NULL);
+ unsigned long long current_microseconds =
+ static_cast<unsigned long long>(current_time.tv_sec) * 1000000 +
+ current_time.tv_usec;
+ pad.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds() + event.time -
+ current_microseconds;
+#else
/*
event.time is unsigned long type exported from accessory.
but the real time(us) will overflow if stored with unsigned long type.
*/
pad.timestamp = (GamepadDataFetcher::CurrentTimeInMicroseconds() +
pad.timestamp - current_microseconds);
+#endif
return;
}
if (gamepad_ == nullptr) {
return;
}
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ // handle home key event seperately.
+ // there's homekey press event need to be handled.
+ if (home_event_.value == (long)HomekeyValue::kPressed) {
+ LOG(INFO) << "[Home key]Handle press event.";
+
+ // handle homekey press event first.
+ RefreshOCIGamepadDataEachEvent(home_event_);
+
+ if (home_key_long_press_status_ == LongPressStatus::kStarted) {
+ /* home key long press enable(1s) but home key press time is less than 1s
+ in such case, home key should be handled as the same as short press. The
+ home key press event will be sent when home key release, and should
+ regenerate home key release event immediately after that.*/
+ home_event_.value = (long)HomekeyValue::kReleased;
+
+ /*for the scenario support home key long press,
+ * the home key release event's timestamp using current timestamp*/
+ struct timeval current_time;
+ gettimeofday(¤t_time, NULL);
+ unsigned long long current_microseconds =
+ static_cast<unsigned long long>(current_time.tv_sec) * 1000000 +
+ current_time.tv_usec;
+ home_event_.time = current_microseconds;
+ home_key_long_press_status_ = LongPressStatus::kEnd;
+ }
+ } else if (home_event_.value == (long)HomekeyValue::kReleased) {
+ /*there's homekey release event need to be handled.*/
+ LOG(INFO) << "[Home key]Handle release event.";
+ RefreshOCIGamepadDataEachEvent(home_event_);
+ home_event_.value = (long)HomekeyValue::kNoEvent;
+ }
CHECK(OCIGamepadItem::kOCIGamepadItemsLength >= s_oci_gamepaditem_num_);
int count = OCIGamepadItem::kOCIGamepadItemsLength;
memset(events_, 0, sizeof(OCIControllerEvent) * count);
+ if (OCI_OK == gamepad_->GetInputEvents(events_, count)) {
+ for (int i = 0; i < count; i++) {
+ RefreshOCIGamepadDataEachEvent(events_[i]);
+ }
+ }
+#else
+ CHECK(OCIGamepadItem::kOCIGamepadItemsLength >= s_oci_gamepaditem_num_);
+
+ int count = OCIGamepadItem::kOCIGamepadItemsLength;
+ memset(events_, 0, sizeof(OCIControllerEvent) * count);
if (OCI_OK == gamepad_->GetInputEventEx(events_, count)) {
for (int i = 0; i < count; i++) {
- RefreshOCIGamepadDataEachEvent(events_[i], count);
+ RefreshOCIGamepadDataEachEvent(events_[i]);
}
}
+#endif
}
void OCIGamepadItem::SetVibration(mojom::GamepadEffectParametersPtr params) {
return weak_factory_.GetWeakPtr();
}
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+void OCIGamepadItem::UpdateGameHomeAppStatus(keynode_t* key) {
+ base::AutoLock lock(home_key_long_press_setting_lock_);
+ home_key_long_press_setting_ = vconf_keynode_get_int(key);
+ LOG(INFO) << "Gamehome APP status changed to "
+ << home_key_long_press_setting_;
+}
+
+void OCIGamepadItem::GamepadHomekeyCallback(OCIControllerEvent event,
+ void* data) {
+ if (data == nullptr) {
+ return;
+ }
+
+ LOG(INFO) << "Enter GamepadHomekeyCallback with home key value "
+ << event.value;
+ OCIGamepadItem* pInstance = (OCIGamepadItem*)data;
+
+ base::AutoLock lock(pInstance->home_key_long_press_setting_lock_);
+ if (event.value == OCI_KEY_PRESSED) {
+ LOG(INFO) << "[Home key] press event.";
+ if (pInstance->home_key_long_press_setting_ >
+ GAMEHOME_STATUS_CLOUDGAME_IS_RUNNING_CONDITION) {
+ LOG(INFO) << "[Home key] GameAPP is running, start timer for long press";
+ pInstance->home_event_.time = event.time;
+ pInstance->home_key_long_press_status_ = LongPressStatus::kStarted;
+ pInstance->home_key_long_press_timer_.Start(
+ FROM_HERE,
+ base::Milliseconds(pInstance->home_key_long_press_setting_),
+ pInstance, &OCIGamepadItem::LongPressCallback);
+
+ } else if ((pInstance->home_key_long_press_setting_ ==
+ GAMEHOME_STATUS_NO_CLOUDGAME_RUNNING ||
+ pInstance->home_key_long_press_setting_ ==
+ GAMEHOME_STATUS_DEFAULT)) {
+ LOG(INFO)
+ << "[Home key]No GameAPP running, set press event to be handled.";
+ pInstance->home_event_.value = (long)HomekeyValue::kPressed;
+ /*for the scenario that not support homekey long press,
+ * home_event_ contains correct timestamp for press and release;
+ * for the scenario that support homekey long press,
+ * home_event_ contains correct press event timestamp,
+ * for release event timestamp, it use current timestamp*/
+ pInstance->home_event_.time = event.time;
+ pInstance->home_key_long_press_status_ = LongPressStatus::kNone;
+ }
+ } else if (event.value == OCI_KEY_RELEASED) {
+ LOG(INFO) << "[Home key] release event.";
+ if (pInstance->home_key_long_press_setting_ >
+ GAMEHOME_STATUS_CLOUDGAME_IS_RUNNING_CONDITION) {
+ if (pInstance->home_key_long_press_status_ == LongPressStatus::kStarted) {
+ /*long press enable case: home key press time is not more than long
+ * press setting time(1s currently)*/
+ LOG(INFO)
+ << "[Home key] GameAPP is running, short press' release event,"
+ << "stop timer and set press event to be handled.";
+ pInstance->home_key_long_press_timer_.Stop();
+ pInstance->home_event_.value = (long)HomekeyValue::kPressed;
+ /*release event's timestamp will be set in RefreshOCIGamepadData.
+ * because home_event_ current contains press event timestamp,
+ * there may be 3ms delay(thread poll interval)
+ */
+ }
+ } else if (pInstance->home_key_long_press_setting_ ==
+ GAMEHOME_STATUS_NO_CLOUDGAME_RUNNING ||
+ pInstance->home_key_long_press_setting_ ==
+ GAMEHOME_STATUS_DEFAULT) {
+ // gameapp is not running, set release status.
+ LOG(INFO)
+ << "[Home key]No GameAPP running, set release event to be handled.";
+ pInstance->home_event_.value = (long)HomekeyValue::kReleased;
+ pInstance->home_event_.time = event.time;
+ pInstance->home_key_long_press_status_ = LongPressStatus::kNone;
+ }
+ }
+}
+
+void OCIGamepadItem::LongPressCallback() {
+ LOG(ERROR) << "[Home key] LongPressCallback";
+ if (home_key_long_press_status_ == LongPressStatus::kStarted) {
+ LOG(INFO) << "[Home key] long pressed! sent gamehome virtualkey!";
+ VirtualKey_Send_KeyCode(VIRTUAL_KEY_GAMEHOME, AUTO_PRESS_RELEASE);
+ home_key_long_press_status_ = LongPressStatus::kEnd;
+ }
+
+ home_key_long_press_timer_.Stop();
+}
+#endif
} // namespace device
#ifndef TIZEN_SRC_EWK_EFL_INTEGRATION_BROWSER_GAMEPAD_OCI_GAMEPAD_ITEM_H_
#define TIZEN_SRC_EWK_EFL_INTEGRATION_BROWSER_GAMEPAD_OCI_GAMEPAD_ITEM_H_
-#include <accessory/GamepadEntry.h>
-#include <accessory/IGamepad.h>
-#include <accessory/OCICommon.h>
+#include <vconf/vconf.h>
#include <memory>
#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/timer/timer.h"
+#include "build/tizen_version.h"
#include "device/gamepad/abstract_haptic_gamepad.h"
#include "device/gamepad/gamepad_data_fetcher.h"
#include "device/gamepad/public/cpp/gamepad.h"
-namespace device {
+#include <accessory/GamepadEntry.h>
+#include <accessory/IGamepad.h>
+#include <accessory/OCICommon.h>
+
+#define VCONF_GAMEHOME_STATUS "memory/accessory/gamehome_status"
+#define GAMEHOME_STATUS_DEFAULT 0 // default value, ghdaemon not exist
+#define GAMEHOME_STATUS_NO_CLOUDGAME_RUNNING 1
+#define GAMEHOME_STATUS_CLOUDGAME_IS_RUNNING_CONDITION 100
+enum class HomekeyValue { kReleased = 0, kPressed = 1, kNoEvent = -1 };
+enum class LongPressStatus {
+ kStarted = 0, // start to handle long press event
+ kEnd = 1, // long press event handle completed.
+ kNone = 2 // not enable long press
+};
+namespace device {
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+class OCIGamepadItem : public AbstractHapticGamepad {
+#else
class OCIGamepadItem : public gamepad::CGamepadCallback,
public AbstractHapticGamepad {
+#endif
public:
~OCIGamepadItem() override;
void SetVibration(mojom::GamepadEffectParametersPtr params) override;
base::WeakPtr<AbstractHapticGamepad> GetWeakPtr() override;
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ // since tizen8.0, home key long press feature
+ // of cloudgame app is handled in chromium side.
+ void UpdateGameHomeAppStatus(keynode_t* key);
+
+ // callback function to handle home key event.
+ static void GamepadHomekeyCallback(OCIControllerEvent event, void* data);
+ // callback function to handle home key long press
+ void LongPressCallback();
+#else
protected:
// Cannot follow google naming style, because it's override from
// CGamepadCallback
void* pparam1,
void* pparam2,
void* pparam3) override;
+#endif
private:
float range_tizen_stick_baseline_;
bool InitAxisRangeTizen();
bool InitAxisRangeTizen(int code, float* baseline, float* range);
- void RefreshOCIGamepadDataEachEvent(const OCIControllerEvent& event,
- const int index);
+ void RefreshOCIGamepadDataEachEvent(const OCIControllerEvent& event);
static size_t s_oci_gamepaditem_num_;
static const float kRangeTizenAxisValueAbsZRz;
static const float kRangeTizenAxisValueAbsXYRxRy;
-
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+ /*added for home key long press feature.
+ 0: ghdaemon doesn't exist
+ 1: ghdaemon exist
+ 1000: ghdaemon exist and cloud game app in gamehub has been
+ running(background/forground) home key long press enable; press time = 1s*/
+ int home_key_long_press_setting_;
+
+ /* lock longpress_limit_time_, it will be changed in
+ GameHomeAPPStatusChangeCallback(mainthread) and accessed in
+ GamepadHomekeyCallback(poll thread)*/
+ base::Lock home_key_long_press_setting_lock_;
+
+ OCIControllerEvent home_event_; // home key event to be handled
+ LongPressStatus home_key_long_press_status_;
+ base::OneShotTimer
+ home_key_long_press_timer_; // timer to check home key long press
+#endif
IGamepadManager* manager_;
OCIDevInfo info_;
IGamepad* gamepad_;