[M108 Aura Migration][NaCl][W3C][Gamepad]Support gamepad w3c apis 47/290247/3
authorweijun <weijun5.lin@samsung.com>
Wed, 22 Mar 2023 01:56:20 +0000 (09:56 +0800)
committerBot Blink <blinkbot@samsung.com>
Thu, 23 Mar 2023 04:56:18 +0000 (04:56 +0000)
Ported patches from tizen_7.0:
      https://review.tizen.org/gerrit/#/c/platform/framework/web/chromium-efl/+/281296/

Change-Id: Ifeaa6a9d4dbf57be3f639076c6ae719e519365db
Signed-off-by: weijun <weijun5.lin@samsung.com>
device/gamepad/gamepad_pad_state_provider.h
device/gamepad/gamepad_platform_data_fetcher.h
packaging/chromium-efl.spec
tizen_src/build/BUILD.gn
tizen_src/build/config/BUILD.gn
tizen_src/build/config/tizen_features.gni
tizen_src/ewk/efl_integration/BUILD.gn
tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.h [new file with mode: 0644]

index d4da9a7..4af335d 100644 (file)
@@ -39,7 +39,8 @@ enum class GamepadSource {
   kWinMr,
   kOpenxr,
   kWinWgi,
-  kMaxValue = kWinWgi,
+  kTizenTv,
+  kMaxValue = kTizenTv,
 };
 
 struct PadState {
index 3c84761..06ef206 100644 (file)
@@ -27,6 +27,8 @@
 #include "device/gamepad/gamepad_platform_data_fetcher_mac.h"
 #include "device/gamepad/nintendo_data_fetcher.h"
 #include "device/gamepad/xbox_data_fetcher_mac.h"
+#elif BUILDFLAG(IS_TIZEN_TV) && defined(USE_TIZEN_TV_ACCESSORY)
+#include "tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h"
 #elif (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(USE_UDEV)
 #include "device/gamepad/gamepad_platform_data_fetcher_linux.h"
 #include "device/gamepad/nintendo_data_fetcher.h"
@@ -59,6 +61,9 @@ void AddGamepadPlatformDataFetchers(GamepadDataFetcherManager* manager) {
   manager->AddFactory(new NintendoDataFetcher::Factory());
   manager->AddFactory(new XboxDataFetcher::Factory());
 
+#elif BUILDFLAG(IS_TIZEN_TV) && defined(USE_TIZEN_TV_ACCESSORY)
+  manager->AddFactory(static_cast<device::GamepadDataFetcherFactory*>(
+      new GamepadPlatformDataFetcherTizenTV::Factory()));
 #elif (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(USE_UDEV)
 
   manager->AddFactory(new GamepadPlatformDataFetcherLinux::Factory(
index 360a7d8..9f37ad3 100755 (executable)
@@ -291,6 +291,10 @@ BuildRequires: pkgconfig(capi-ui-inputmethod)
 BuildRequires: squashfs
 %endif
 
+%if "%{?tizen_profile_name}" == "tv" && "%{_vd_cfg_product_type}" != "AUDIO" &&  "%{_vd_cfg_product_type}" != "AV"
+BuildRequires: pkgconfig(accessory)
+%endif
+
 %if 0%{?__generate_tpk} || 0%{?__package_signing}
 BuildRequires: hash-signer, zip
 %endif
@@ -478,6 +482,9 @@ touch ./tizen_src/downloadable/ewk_api_wrapper_generator.py
 %if "%{?tizen_profile_name}" == "tv"
   "tizen_product_tv=true" \
 %endif
+%if "%{?tizen_profile_name}" == "tv" && "%{_vd_cfg_product_type}" != "AUDIO" &&  "%{_vd_cfg_product_type}" != "AV"
+  "tizen_vd_accessory=true" \
+%endif
 %if 0%{?component_build}
  "component=\"shared_library\"" \
 %endif
index 56db169..712155b 100644 (file)
@@ -844,6 +844,13 @@ tizen_pkg_config("privileged-service") {
   }
 }
 
+tizen_pkg_config("accessory") {
+  packages = []
+  if (tizen_vd_accessory) {
+    packages = [ "accessory" ]
+  }
+}
+
 if (enable_wrt_js) {
   tizen_pkg_config("appcore-agent") {
     packages = [ "appcore-agent" ]
index 335ec68..9cd713a 100644 (file)
@@ -98,4 +98,10 @@ config("tizen_feature_flags") {
       "TIZEN_PEPPER_EXTENSIONS"
     ]
   }
+  if (tizen_vd_accessory) {
+    defines += [
+      "USE_TIZEN_TV_ACCESSORY",
+      "_LINUX",
+    ]
+  }
 }
index c4eb0fe..7712d5f 100644 (file)
@@ -65,6 +65,7 @@ declare_args() {
 
   tizen_autofill = false
   tizen_autofill_fw = false
+  tizen_vd_accessory = false
 
   tizen_resource_manager = false
 }
index 67dcfee..dcdf97b 100644 (file)
@@ -122,7 +122,9 @@ shared_library("chromium-ewk") {
   if (enable_basic_printing) {
     deps += [ "//printing" ]
   }
-
+  if (tizen_vd_accessory) {
+    configs += [ "//tizen_src/build:accessory" ]
+  }
   chrome_version = exec_script(version_script,
                                [
                                  "-f",
@@ -133,7 +135,6 @@ shared_library("chromium-ewk") {
                                "trim string",
                                [])
   defines = [ "CHROMIUM_VERSION=\"" + chrome_version + "\"" ]
-
   ldflags = [
     "-Wl,--no-undefined",
     "-Wl,--version-script=" +
@@ -730,6 +731,16 @@ shared_library("chromium-ewk") {
     ]
   }
 
+  if (tizen_vd_accessory){
+    sources += [
+      # add tizen_tv gamepad platform data fetcher
+      "browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.cc",
+      "browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h",
+      "browser/gamepad/oci_gamepad_item.cc",
+      "browser/gamepad/oci_gamepad_item.h",
+    ]
+  }
+
   sources -= exclude_source_set
 
   # FIXME: Followings are guarded just for bringup.
diff --git a/tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.cc b/tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.cc
new file mode 100644 (file)
index 0000000..7cc7b7a
--- /dev/null
@@ -0,0 +1,351 @@
+// Copyright 2016 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h"
+#include <string.h>
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
+
+namespace device {
+
+void GamepadPlatformDataFetcherTizenTV::GetPidVid(const char* uid,
+                                                  std::string* pid,
+                                                  std::string* vid) {
+  // * @brief    just get pid and vid from uid information
+  // * @param    [in]     - uid information  char[]
+  // * @param    [out]    - pid
+  // * @param    [out]    - vid
+  //
+  // eg. id
+  // Microsoft Corporation Controller (STANDARD GAMEPAD Vendor: 045e Product:
+  // 028e)
+  // GetUID() :          USB\VID_045e\PID_028e\-/75
+  //                     vid: 045e,  pid: 028e
+  // GetGamepadName() :  Microsoft Corporation Controller
+
+  int position_vid = 0;
+  int position_pid = 0;
+  int position_second = 0;
+  int position_third = 0;
+
+  std::string str_vp(uid);
+
+  position_vid = str_vp.find("VID_");
+  position_pid = str_vp.find("PID_");
+
+  position_second = str_vp.find("\\", position_vid);
+  position_third = str_vp.find("\\", position_pid);
+
+  (*vid) = str_vp.substr(position_vid + 4, position_second - position_vid - 4);
+  (*pid) = str_vp.substr(position_pid + 4, position_third - position_pid - 4);
+}
+
+void GamepadPlatformDataFetcherTizenTV::UTF8toUTF16(char16_t utf_16_str[],
+                                                    size_t utf_16_str_size,
+                                                    std::string str,
+                                                    size_t str_length) {
+  base::TruncateUTF8ToByteSize(str, str_length - 1, &str);
+  std::u16string tmp16 = base::UTF8ToUTF16(str);
+  memset(utf_16_str, 0, utf_16_str_size);
+  tmp16.copy(utf_16_str, utf_16_str_size - 1);
+}
+
+void GamepadPlatformDataFetcherTizenTV::MapperTizenStyleGamepad(
+    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]);
+  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];
+  mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
+
+  mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
+  mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
+  mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
+  mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+      AxisPositiveAsButton(input.axes[6]);
+
+  mapped->buttons[BUTTON_INDEX_META] = input.buttons[14];
+  mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+  mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+  mapped->buttons_length = BUTTON_INDEX_COUNT;
+  mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
+GamepadPlatformDataFetcherTizenTV::GamepadPlatformDataFetcherTizenTV() {
+  gamepad_manager_ = nullptr;
+  if (Gamepad_Create()) {
+    Initialize();
+  } else {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::"
+                  "GamepadPlatformDataFetcherTizenTV() Gamepad_Create() ERROR "
+                  "!!!";
+  }
+}
+
+GamepadPlatformDataFetcherTizenTV::~GamepadPlatformDataFetcherTizenTV() {
+  CHECK(gamepad_manager_ != nullptr);
+  gamepad_manager_->UnregisterCallback(this);
+
+  // Need set gamepad_items_ to null before Gamepad_Destroy, caused by business
+  // logic
+  for (size_t i = 0; i < Gamepads::kItemsLengthCap; i++) {
+    if (gamepad_items_[i] != nullptr) {
+      gamepad_items_[i]->Shutdown();
+      gamepad_items_[i] = nullptr;
+    }
+  }
+  Gamepad_Destroy();
+}
+
+void GamepadPlatformDataFetcherTizenTV::Initialize() {
+  gamepad_manager_ = Gamepad_GetManager();
+  if (gamepad_manager_ == nullptr) {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::Initialize() "
+                  "Gamepad_GetManager() handle get fail !!! ";
+    return;
+  }
+
+  InitTizenDevice();
+  EnumerateTizenDevices();
+  gamepad_manager_->RegisterCallback(this);
+}
+
+void GamepadPlatformDataFetcherTizenTV::InitTizenDevice() {
+  LOG(INFO) << "InitTizenDevice  Gamepads::kItemsLengthCap "
+            << Gamepads::kItemsLengthCap;
+
+  for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) {
+    Gamepad& pad = data_.items[i];
+    pad.connected = false;
+  }
+}
+
+void GamepadPlatformDataFetcherTizenTV::EnumerateTizenDevices() {
+  CHECK(gamepad_manager_ != nullptr);
+
+  for (size_t i = 0; i < Gamepads::kItemsLengthCap; i++) {
+    OCIDevInfo dev_info;
+    bool bIsFree;
+
+    if (gamepad_manager_->GetConnectedDeviceInfo(dev_info, bIsFree, i) !=
+        OCI_OK) {
+      continue;
+    }
+    LOG(INFO) << " dev_info.deviceType " << dev_info.deviceType
+              << " dev_info.eventTyp " << dev_info.eventType
+              << " dev_info.profileType " << dev_info.profileType
+              << " dev_info.UID " << dev_info.UID << " dev_info.name "
+              << dev_info.name << " bIsFree " << bIsFree;
+
+    if (gamepad_items_[i] == nullptr) {
+      gamepad_items_[i] = OCIGamepadItem::Create(gamepad_manager_, &dev_info,
+                                                 &data_.items[i], i);
+      if (gamepad_items_[i]) {
+        InitMapping(i);
+      }
+    }
+  }
+}
+
+void GamepadPlatformDataFetcherTizenTV::GetGamepadData(
+    bool devices_changed_hint) {
+  TRACE_EVENT0("GAMEPAD", "GetGamepadData");
+  // Update our internal state.
+  for (size_t i = 0; i < Gamepads::kItemsLengthCap; ++i) {
+    if (gamepad_items_[i] != nullptr) {
+      ReadTizenDeviceData(i);
+
+      PadState* state = GetPadState(i);
+      if (!state)
+        return;
+
+      Gamepad& pad = state->data;
+      MapperTizenStyleGamepad(data_.items[i], &pad);
+    }
+  }
+}
+
+GamepadSource GamepadPlatformDataFetcherTizenTV::source() {
+  return Factory::static_source();
+}
+
+void GamepadPlatformDataFetcherTizenTV::ReadTizenDeviceData(size_t index) {
+  // Linker does not like CHECK_LT(index, Gamepads::kItemsLengthCap). =/
+  if (index >= Gamepads::kItemsLengthCap) {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::ReadTizenDeviceData() "
+               << "index >= Gamepads::kItemsLengthCap";
+    return;
+  }
+  CHECK(gamepad_items_[index] != nullptr);
+  gamepad_items_[index]->RefreshOCIGamepadData();
+}
+
+void GamepadPlatformDataFetcherTizenTV::InitMapping(size_t index) {
+  if (index >= Gamepads::kItemsLengthCap) {
+    LOG(ERROR)
+        << "[Gamepad_LOG] GamepadPlatformDataFetcherTizenTV::InitMapping() "
+        << "index >= Gamepads::kItemsLengthCap";
+    return;
+  }
+
+  Gamepad& pad = data_.items[index];
+
+  // reset memory to zero
+  memset(pad.buttons, 0, (sizeof(pad.buttons[0])) * Gamepad::kButtonsLengthCap);
+  memset(pad.axes, 0, (sizeof(pad.axes[0])) * Gamepad::kAxesLengthCap);
+  pad.axes[2] = -1.0;
+  pad.axes[5] = -1.0;
+  pad.buttons_length = 0;
+  pad.axes_length = 0;
+  pad.timestamp = 0;
+  pad.mapping = GamepadMapping::kStandard;
+
+  CHECK(gamepad_items_[index] != nullptr);
+
+  std::string vid = "";
+  std::string pid = "";
+
+  GetPidVid(gamepad_items_[index]->GetUID(), &pid, &vid);
+
+  std::string name_string(gamepad_items_[index]->GetGamepadName());
+
+  std::string id =
+      name_string + base::StringPrintf(" (%sVendor: %s Product: %s)",
+                                       "STANDARD GAMEPAD ", vid.c_str(),
+                                       pid.c_str());
+
+  UTF8toUTF16(pad.id, sizeof(pad.id), id, Gamepad::kIdLengthCap);
+}
+
+void GamepadPlatformDataFetcherTizenTV::t_OnCallback(int type,
+                                                     void* pparam1,
+                                                     void* pparam2,
+                                                     void* pparam3) {
+  int evType = 0;
+  OCIDevInfo dev_info;
+  std::string sType = "";
+
+  if (type == OCI_EVENT_DEV_CONNECT)
+    sType = " CONNECT ";
+  else if (type == OCI_EVENT_DEV_DISCONNECT)
+    sType = " DISCONNECT ";
+
+  LOG(INFO) << sType << " pparam1 " << reinterpret_cast<char*>(pparam1);
+
+  if (t_GetDevManagerEventData(evType, dev_info,
+                               reinterpret_cast<char*>(pparam1)) != OCI_OK) {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::t_OnCallback() "
+               << sType << "error != OCI_OK";
+
+    return;
+  }
+  LOG(INFO) << " dev_info.deviceType " << dev_info.deviceType
+            << " dev_info.eventTyp " << dev_info.eventType
+            << " dev_info.profileType " << dev_info.profileType
+            << " dev_info.UID " << dev_info.UID << " dev_info.name "
+            << dev_info.name;
+
+  if (dev_info.deviceType != OCI_DEVICE_JOYSTICK) {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::t_OnCallback() "
+               << sType << "error != OCI_DEVICE_JOYSTICK ";
+    return;
+  }
+
+  switch (type) {
+    case OCI_EVENT_DEV_CONNECT: {
+      for (size_t i = 0; i < Gamepads::kItemsLengthCap; i++) {
+        if (gamepad_items_[i] == nullptr) {
+          LOG(INFO) << " connected";
+          gamepad_items_[i] = OCIGamepadItem::Create(
+              gamepad_manager_, &dev_info, &data_.items[i], i);
+          if (gamepad_items_[i]) {
+            InitMapping(i);
+            break;
+          }
+        } else {
+          continue;
+        }
+      }
+      break;
+    }
+
+    case OCI_EVENT_DEV_DISCONNECT: {
+      for (size_t i = 0; i < Gamepads::kItemsLengthCap; i++) {
+        if (gamepad_items_[i] != nullptr &&
+            (strcmp(gamepad_items_[i]->GetUID(), dev_info.UID) == 0)) {
+          LOG(INFO) << " gamepad_items_[" << i << "]->GetUID() "
+                    << gamepad_items_[i]->GetUID();
+          LOG(INFO) << " disconnected";
+          gamepad_items_[i]->Shutdown();
+          gamepad_items_[i] = nullptr;
+          break;
+        }
+      }
+      break;
+    }
+    case OCI_EVENT_DEV_STATUS: {
+      break;
+    }
+    default: {
+      break;
+    }
+  }
+}
+
+void GamepadPlatformDataFetcherTizenTV::PlayEffect(
+    int pad_id,
+    mojom::GamepadHapticEffectType type,
+    mojom::GamepadEffectParametersPtr params,
+    mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback,
+    scoped_refptr<base::SequencedTaskRunner> callback_runner) {
+  if (pad_id < 0 || pad_id >= Gamepads::kItemsLengthCap) {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::PlayEffect() "
+               << "index >= Gamepads::kItemsLengthCap";
+    return;
+  }
+  if (gamepad_items_[pad_id] == nullptr) {
+    RunVibrationCallback(
+        std::move(callback), std::move(callback_runner),
+        mojom::GamepadHapticsResult::GamepadHapticsResultError);
+    return;
+  }
+  gamepad_items_[pad_id]->PlayEffect(
+      type, std::move(params), std::move(callback), std::move(callback_runner));
+}
+
+void GamepadPlatformDataFetcherTizenTV::ResetVibration(
+    int pad_id,
+    mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback,
+    scoped_refptr<base::SequencedTaskRunner> callback_runner) {
+  if (pad_id < 0 || pad_id >= Gamepads::kItemsLengthCap) {
+    LOG(ERROR) << "[Gamepad_LOG] "
+                  "GamepadPlatformDataFetcherTizenTV::ResetVibration() "
+               << "index >= Gamepads::kItemsLengthCap";
+    return;
+  }
+  if (gamepad_items_[pad_id] == nullptr) {
+    RunVibrationCallback(
+        std::move(callback), std::move(callback_runner),
+        mojom::GamepadHapticsResult::GamepadHapticsResultError);
+    return;
+  }
+
+  gamepad_items_[pad_id]->ResetVibration(std::move(callback),
+                                         std::move(callback_runner));
+}
+
+}  // namespace device
\ No newline at end of file
diff --git a/tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h b/tizen_src/ewk/efl_integration/browser/gamepad/gamepad_platform_data_fetcher_tizen_tv.h
new file mode 100644 (file)
index 0000000..0d6c747
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2016 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_EWK_EFL_INTEGRATION_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_TIZEN_TV_H_
+#define TIZEN_SRC_EWK_EFL_INTEGRATION_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_TIZEN_TV_H_
+
+#include <accessory/GamepadCallback.h>
+#include <accessory/GamepadEntry.h>
+#include <accessory/IGamepad.h>
+#include <accessory/OCICommon.h>
+#include <array>
+#include <memory>
+#include <string>
+#include "device/gamepad/gamepad_data_fetcher.h"
+#include "device/gamepad/gamepad_pad_state_provider.h"
+#include "device/gamepad/gamepad_standard_mappings.h"
+#include "device/gamepad/public/cpp/gamepad.h"
+#include "tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.h"
+
+namespace device {
+
+class GamepadPlatformDataFetcherTizenTV
+    : public device::GamepadDataFetcher,
+      public gamepad::CGamepadManagerCallback {
+ public:
+  typedef device::GamepadDataFetcherFactoryImpl<
+      GamepadPlatformDataFetcherTizenTV,
+      device::GamepadSource::kTizenTv>
+      Factory;
+  GamepadPlatformDataFetcherTizenTV();
+  ~GamepadPlatformDataFetcherTizenTV() override;
+
+  // GamepadDataFetcher implementation.
+  void GetGamepadData(bool devices_changed_hint) override;
+  GamepadSource source() override;
+
+  void PlayEffect(int source_id,
+                  mojom::GamepadHapticEffectType,
+                  mojom::GamepadEffectParametersPtr,
+                  mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback,
+                  scoped_refptr<base::SequencedTaskRunner>) override;
+  void ResetVibration(
+      int source_id,
+      mojom::GamepadHapticsManager::ResetVibrationActuatorCallback,
+      scoped_refptr<base::SequencedTaskRunner>) override;
+
+ protected:
+  virtual void t_OnCallback(int type,
+                            void* pparam1,
+                            void* pparam2,
+                            void* pparam3);
+
+ private:
+  void ReadTizenDeviceData(size_t index);
+  void EnumerateTizenDevices();
+
+  void InitTizenDevice();
+  void Initialize();
+  void InitMapping(size_t index);
+
+  // Notice: [in] uid, [out] pid, [out] vid
+  void GetPidVid(const char* uid, std::string* pid, std::string* vid);
+  void UTF8toUTF16(char16_t utf_16_str[],
+                   size_t utf_16_str_size,
+                   std::string str,
+                   size_t str_length);
+
+  // Functions to map from device data to standard layout.
+  static void MapperTizenStyleGamepad(const Gamepad& input, Gamepad* mapped);
+
+  // Data that's returned to the consumer.
+  Gamepads data_;
+
+  gamepad::IGamepadManager* gamepad_manager_;
+  std::array<std::unique_ptr<OCIGamepadItem>, Gamepads::kItemsLengthCap>
+      gamepad_items_;
+};
+
+}  // namespace device
+
+#endif  // TIZEN_SRC_EWK_EFL_INTEGRATION_BROWSER_GAMEPAD_GAMEPAD_PLATFORM_DATA_FETCHER_TIZEN_TV_H_
diff --git a/tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.cc b/tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.cc
new file mode 100644 (file)
index 0000000..911d140
--- /dev/null
@@ -0,0 +1,263 @@
+// Copyright 2016 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.h"
+#include <utility>
+#include "base/logging.h"
+
+namespace device {
+
+size_t OCIGamepadItem::s_oci_gamepaditem_num_ = 0;
+
+// static function
+std::unique_ptr<OCIGamepadItem> OCIGamepadItem::Create(IGamepadManager* manager,
+                                                       OCIDevInfo* dev_info,
+                                                       Gamepad* pad,
+                                                       int index) {
+  if (manager == nullptr) {
+    return nullptr;
+  }
+  auto gamepad_item = std::unique_ptr<OCIGamepadItem>(
+      new OCIGamepadItem(manager, dev_info, pad));
+  if (!gamepad_item->CreateDevice()) {
+    return nullptr;
+  }
+  gamepad_item->SetOCIGamepadItemIndex(index);
+  return gamepad_item;
+}
+
+bool OCIGamepadItem::InitAxisRangeTizen(int code,
+                                        float* baseline,
+                                        float* range) {
+  if (gamepad_ == nullptr) {
+    LOG(ERROR) << "[Gamepad_LOG] OCIGamepadItem::InitAxisRangeTizen() "
+                  "gamepad_ == nullptr return";
+    return false;
+  }
+
+  // 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;
+    return true;
+  } else {
+    LOG(ERROR) << "[Gamepad_LOG] OCIGamepadItem::InitAxisRangeTizen(int "
+                  "code, float* range) init error, code = "
+               << code;
+    return false;
+  }
+}
+
+bool OCIGamepadItem::InitAxisRangeTizen() {
+  // OCI_ABS_X, OCI_ABS_Y, OCI_ABS_RX, OCI_ABS_RY has same range
+  // OCI_ABS_Z, OCI_ABS_RZ has same range
+
+  return InitAxisRangeTizen(OCI_ABS_X, &range_tizen_stick_baseline_,
+                            &range_tizen_stick_range_) &&
+         InitAxisRangeTizen(OCI_ABS_Z, &range_tizen_trigger_baseline_,
+                            &range_tizen_trigger_range_);
+}
+
+OCIGamepadItem::OCIGamepadItem(IGamepadManager* manager,
+                               OCIDevInfo* info,
+                               Gamepad* pad) {
+  CHECK(info != nullptr);
+  memcpy(&info_, info, sizeof(OCIDevInfo));
+  CHECK(manager != nullptr);
+  manager_ = manager;
+  gamepad_ = nullptr;
+  pad_ = pad;
+
+  range_tizen_stick_baseline_ = 0.0;
+  range_tizen_stick_range_ = 0.0;
+  range_tizen_trigger_baseline_ = 0.0;
+  range_tizen_trigger_range_ = 0.0;
+
+  s_oci_gamepaditem_num_++;
+}
+
+OCIGamepadItem::~OCIGamepadItem() {
+  if (gamepad_ == nullptr)  // CreateDevice fail, need not destroy device.
+    return;
+  this->DestroyDevice();
+  s_oci_gamepaditem_num_--;
+}
+
+bool OCIGamepadItem::CreateDevice() {
+  CHECK(manager_ != nullptr);
+  gamepad_ = manager_->CreateDevice(info_.UID);
+  if (gamepad_ == nullptr) {
+    LOG(ERROR)
+        << "[Gamepad_LOG] OCIGamepadItem::Create() gamepad_ == nullptr return";
+    return false;
+  }
+
+  CHECK(pad_ != nullptr);
+  pad_->connected = true;
+  pad_->vibration_actuator.not_null = gamepad_->IsForceFeedbackSupported();
+  if (pad_->vibration_actuator.not_null)
+    pad_->vibration_actuator.type = GamepadHapticActuatorType::kDualRumble;
+
+  return InitAxisRangeTizen();
+}
+
+void OCIGamepadItem::DestroyDevice() {
+  CHECK(manager_ != nullptr);
+  CHECK(gamepad_ != nullptr);
+  CHECK(pad_ != nullptr);
+
+  manager_->DestroyDevice(gamepad_->GetID());
+  gamepad_ = nullptr;
+  pad_->connected = false;
+
+  return;
+}
+
+void OCIGamepadItem::t_OnCallback(int type,
+                                  void* pparam1,
+                                  void* pparam2,
+                                  void* pparam3) {
+  // used by parent class
+}
+
+const char* OCIGamepadItem::GetUID() {
+  LOG(INFO) << "GamePad " << info_.UID;
+  return info_.UID;
+}
+
+const char* OCIGamepadItem::GetGamepadName() {
+  LOG(INFO) << "GamePad " << info_.name;
+  return info_.name;
+}
+
+void OCIGamepadItem::SetOCIGamepadItemIndex(size_t index) {
+  index_ = index;
+}
+
+size_t OCIGamepadItem::GetItemIndex() {
+  return index_;
+}
+
+void OCIGamepadItem::RefreshOCIGamepadDataEachEvent(
+    const OCIControllerEvent& event,
+    const int index) {
+  Gamepad& pad = (*pad_);
+  size_t item = event.code;
+  if (event.type == OCI_EV_ABS) {
+    if (item >= Gamepad::kAxesLengthCap) {
+      // change the keycode index
+      // OCI_ABS_HAT0X & OCI_ABS_HAT0Y  maybe [-1, 0, 1]
+
+      if (event.code == OCI_ABS_HAT0X) {
+        item = 6;
+        pad.axes[item] = event.value;
+        if (item >= pad.axes_length) {
+          pad.axes_length = item + 1;
+        }
+      } else if (event.code == OCI_ABS_HAT0Y) {
+        item = 7;
+        pad.axes[item] = event.value;
+        if (item >= pad.axes_length) {
+          pad.axes_length = item + 1;
+        }
+      } else {
+        LOG(ERROR)
+            << "[Gamepad_LOG] OCIGamepadItem::RefreshOCIGamepadDataEachEvent() "
+            << " set the keycode index Gamepad::axes Error 001 !!!";
+        return;
+      }
+    } else {
+      // convert [0, 255] / [-127, 127]  -> [-1, 1]
+      switch (event.code) {
+        case OCI_ABS_X:   // fallthrough
+        case OCI_ABS_Y:   // fallthrough
+        case OCI_ABS_RX:  // fallthrough
+        case OCI_ABS_RY:
+          pad.axes[item] = (event.value - range_tizen_stick_baseline_) /
+                           range_tizen_stick_range_;
+          break;
+        case OCI_ABS_Z:  // fallthrough
+        case OCI_ABS_RZ:
+          pad.axes[item] = (event.value - range_tizen_trigger_baseline_) /
+                           range_tizen_trigger_range_;
+          break;
+        default:
+          LOG(ERROR) << "[Gamepad_LOG] "
+                        "OCIGamepadItem::RefreshOCIGamepadDataEachEvent() "
+                     << " set the keycode index Gamepad::axes Error 002 !!!";
+          break;
+      }
+
+      if (item >= pad.axes_length) {
+        pad.axes_length = item + 1;
+      }
+    }
+  } else if (event.type == OCI_EV_KEY) {
+    if (item >= Gamepad::kButtonsLengthCap) {
+      LOG(ERROR)
+          << "[Gamepad_LOG] OCIGamepadItem::RefreshOCIGamepadDataEachEvent() "
+          << " set the keycode index Gamepad::buttons Error !!!";
+      return;
+    }
+    pad.buttons[item].pressed = event.value;
+    pad.buttons[item].value = event.value ? 1.0 : 0.0;
+    if (item >= pad.buttons_length) {
+      pad.buttons_length = item + 1;
+    }
+  }
+  pad.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
+  return;
+}
+
+void OCIGamepadItem::RefreshOCIGamepadData() {
+  if (gamepad_ == nullptr) {
+    return;
+  }
+
+  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);
+    }
+  }
+}
+
+void OCIGamepadItem::SetVibration(mojom::GamepadEffectParametersPtr params) {
+  if (gamepad_ == nullptr) {
+    return;
+  }
+
+  if (params->strong_magnitude > 0 || params->weak_magnitude > 0) {
+    // start dual-rumble
+
+    // scope of scaled_strong_magnitude and scaled_weak_magnitude: 0~100
+    int scaled_strong_magnitude = params->strong_magnitude * 100;
+    int scaled_weak_magnitude = params->weak_magnitude * 100;
+
+    // AbstractHapticGamepad will call SetZeroVibration when the effect is
+    // complete, so we don't need to set the duration here except to make sure
+    // it is at least as long as the maximum duration.
+    uint16_t duration_millis =
+        static_cast<uint16_t>(GamepadHapticActuator::kMaxEffectDurationMillis);
+
+    // duration is controlled by AbstractHapticGamepad, set max duration here.
+    gamepad_->PlayHapticForceFeedback(DUAL_RUMBLE_EFFECT_TYPE, duration_millis,
+                                      scaled_weak_magnitude,
+                                      scaled_strong_magnitude);
+  } else {
+    gamepad_->StopForceFeedback();
+  }
+}
+base::WeakPtr<AbstractHapticGamepad> OCIGamepadItem::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+}  // namespace device
diff --git a/tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.h b/tizen_src/ewk/efl_integration/browser/gamepad/oci_gamepad_item.h
new file mode 100644 (file)
index 0000000..e3db6ef
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright 2016 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#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 <memory>
+#include "base/memory/weak_ptr.h"
+#include "device/gamepad/abstract_haptic_gamepad.h"
+#include "device/gamepad/gamepad_data_fetcher.h"
+#include "device/gamepad/public/cpp/gamepad.h"
+
+namespace device {
+
+class OCIGamepadItem : public gamepad::CGamepadCallback,
+                       public AbstractHapticGamepad {
+ public:
+  ~OCIGamepadItem() override;
+
+  // OCIGamepadItem implementation.
+  const char* GetUID();
+  const char* GetGamepadName();
+  size_t GetItemIndex();
+
+  // change the device data.
+  void RefreshOCIGamepadData();
+
+  // static function for create OCIGamepadItem, used by
+  // GamepadPlatformDataFetcherTizenTV
+  static std::unique_ptr<OCIGamepadItem> Create(IGamepadManager* manager,
+                                                OCIDevInfo* dev_info,
+                                                Gamepad* pad,
+                                                int index);
+
+  // Set the vibration magnitude for dual-rumble.
+  void SetVibration(mojom::GamepadEffectParametersPtr params) override;
+
+  base::WeakPtr<AbstractHapticGamepad> GetWeakPtr() override;
+
+ protected:
+  // Cannot follow google naming style, because it's override from
+  // CGamepadCallback
+  void t_OnCallback(int type,
+                    void* pparam1,
+                    void* pparam2,
+                    void* pparam3) override;
+
+ private:
+  float range_tizen_stick_baseline_;
+  float range_tizen_stick_range_;
+  float range_tizen_trigger_baseline_;
+  float range_tizen_trigger_range_;
+
+  static const size_t kOCIGamepadItemsLength = 16;
+  OCIControllerEvent events_[kOCIGamepadItemsLength];
+
+  explicit OCIGamepadItem(IGamepadManager* manager,
+                          OCIDevInfo* info,
+                          Gamepad* pad);
+  bool CreateDevice();
+  void DestroyDevice();
+  void SetOCIGamepadItemIndex(size_t index);
+
+  bool InitAxisRangeTizen();
+  bool InitAxisRangeTizen(int code, float* baseline, float* range);
+  void RefreshOCIGamepadDataEachEvent(const OCIControllerEvent& event,
+                                      const int index);
+  static size_t s_oci_gamepaditem_num_;
+  static const float kRangeTizenAxisValueAbsZRz;
+  static const float kRangeTizenAxisValueAbsXYRxRy;
+
+  IGamepadManager* manager_;
+  OCIDevInfo info_;
+  IGamepad* gamepad_;
+  Gamepad* pad_;
+  size_t index_;
+  base::WeakPtrFactory<OCIGamepadItem> weak_factory_{this};
+};
+
+}  // namespace device
+
+#endif  // TIZEN_SRC_EWK_EFL_INTEGRATION_BROWSER_GAMEPAD_OCI_GAMEPAD_ITEM_H_