external connection: add HAL for external connection 48/71648/1 accepted/tizen/common/20160527.152801 accepted/tizen/ivi/20160527.052259 accepted/tizen/mobile/20160527.051808 accepted/tizen/tv/20160527.052129 accepted/tizen/wearable/20160527.052035 submit/tizen/20160527.033611
authorTaeyoung Kim <ty317.kim@samsung.com>
Thu, 26 May 2016 09:54:26 +0000 (18:54 +0900)
committerTaeyoung Kim <ty317.kim@samsung.com>
Thu, 26 May 2016 09:54:26 +0000 (18:54 +0900)
- HAL is added for external connection such as usb cable
  ans earjack. The HAL handles the signal from emuld.

Change-Id: I27624450dcd4ab40c34a473675615fd76d11c13c
Signed-off-by: Taeyoung Kim <ty317.kim@samsung.com>
CMakeLists.txt
hw/dbus.c [new file with mode: 0644]
hw/dbus.h [new file with mode: 0644]
hw/external_connection/CMakeLists.txt [new file with mode: 0644]
hw/external_connection/external_connection.c [new file with mode: 0644]
packaging/device-manager-plugin-emul.spec

index 27ed342..0f68485 100644 (file)
@@ -33,3 +33,4 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
 
 ADD_SUBDIRECTORY(hw/display)
+ADD_SUBDIRECTORY(hw/external_connection)
diff --git a/hw/dbus.c b/hw/dbus.c
new file mode 100644 (file)
index 0000000..ca14f3f
--- /dev/null
+++ b/hw/dbus.c
@@ -0,0 +1,75 @@
+/*
+ * device-node
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dbus.h"
+#include "shared.h"
+
+int register_dbus_signal(const char *object,
+               const char *iface, const char *signal,
+               GDBusSignalCallback callback, void *data, int *id)
+{
+       GError *err = NULL;
+       GDBusConnection *conn;
+       int sid;
+
+#if !GLIB_CHECK_VERSION(2, 35, 0)
+       g_type_init();
+#endif
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn) {
+               _E("fail to get dbus connection : %s", err->message);
+               g_clear_error(&err);
+               return -EPERM;
+       }
+
+       /* subscribe signal */
+       sid = g_dbus_connection_signal_subscribe(conn,
+                       NULL, iface, signal, object,
+                       NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+                       callback, data, NULL);
+       if (sid == 0) {
+               _E("fail to connect %s signal", signal);
+               return -EPERM;
+       }
+
+       if (id)
+               *id = sid;
+
+       return 0;
+}
+
+void unregister_dbus_signal(int *id)
+{
+       GError *err = NULL;
+       GDBusConnection *conn;
+
+       if (!id || *id <= 0)
+               return;
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn) {
+               _E("fail to get dbus connection : %s", err->message);
+               g_clear_error(&err);
+               return;
+       }
+
+       /* unsubscribe signal */
+       g_dbus_connection_signal_unsubscribe(conn, *id);
+       *id = 0;
+}
diff --git a/hw/dbus.h b/hw/dbus.h
new file mode 100644 (file)
index 0000000..98695d0
--- /dev/null
+++ b/hw/dbus.h
@@ -0,0 +1,32 @@
+/*
+ * libdevice-node
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __HW_DEFAULT_DBUS_H__
+#define __HW_DEFAULT_DBUS_H__
+
+#include <stdio.h>
+#include <errno.h>
+#include <gio/gio.h>
+
+int register_dbus_signal(const char *object,
+               const char *iface, const char *signal,
+               GDBusSignalCallback callback, void *data, int *id);
+void unregister_dbus_signal(int *id);
+
+#endif
diff --git a/hw/external_connection/CMakeLists.txt b/hw/external_connection/CMakeLists.txt
new file mode 100644 (file)
index 0000000..913ceb4
--- /dev/null
@@ -0,0 +1,19 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(external_connection C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(external_connection_pkgs REQUIRED hwcommon dlog glib-2.0 gio-2.0)
+
+FOREACH(flag ${external_connection_pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+ADD_LIBRARY(${PROJECT_NAME} MODULE external_connection.c ../shared.c ../dbus.c)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${external_connection_pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "")
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR}/hw COMPONENT RuntimeLibraries)
diff --git a/hw/external_connection/external_connection.c b/hw/external_connection/external_connection.c
new file mode 100644 (file)
index 0000000..741cc77
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * device-node
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/limits.h>
+#include <dirent.h>
+
+#include <hw/external_connection.h>
+#include "../shared.h"
+#include "../dbus.h"
+
+#define EXTCON_BUS      "org.tizen.system.deviced"
+#define EXTCON_OBJECT   "/Org/Tizen/System/DeviceD/ExtCon"
+#define EXTCON_IFACE    EXTCON_BUS".ExtCon"
+#define EXTCON_SIGNAL   "device_changed"
+
+#define EXTCON_EARJACK  "earjack"
+#define EXTCON_USB      "usb"
+
+#define EXTCON_EARJACK_PATH "/sys/devices/platform/jack/earjack_online"
+#define EXTCON_USB_PATH     "/sys/devices/platform/jack/usb_online"
+
+struct extcon_device {
+       char *name;
+       char *type;
+       char *path;
+} extcon_devices[] = {
+       { EXTCON_USB,     EXTERNAL_CONNECTION_USB,       EXTCON_USB_PATH,     },
+       { EXTCON_EARJACK, EXTERNAL_CONNECTION_HEADPHONE, EXTCON_EARJACK_PATH, },
+};
+
+static int id; /* signal handler id */
+
+static struct signal_data {
+       ConnectionUpdated updated_cb;
+       void *data;
+} sdata = { 0, };
+
+static void signal_delivered(GDBusConnection *conn,
+               const gchar *sender,
+               const gchar *object,
+               const gchar *iface,
+               const gchar *signal,
+               GVariant *parameters,
+               gpointer user_data)
+{
+       struct connection_info info;
+       char *sig, *name, *state;
+       char st[32];
+       int num, i;
+       size_t len;
+       bool found;
+
+       if (strncmp(signal, EXTCON_SIGNAL, sizeof(EXTCON_SIGNAL)))
+               return;
+
+       g_variant_get(parameters, "(siss)", &sig, &num, &name, &state);
+
+       _I("extcon uevent is delivered: (%s) state (%s)", name, state);
+
+       found = false;
+       len = strlen(name) + 1;
+       for (i = 0 ; i < ARRAY_SIZE(extcon_devices) ; i++) {
+               if (strncmp(name, extcon_devices[i].name, len))
+                       continue;
+               found = true;
+               break;
+       }
+       if (!found)
+               goto out;
+
+       info.name = extcon_devices[i].type;
+       snprintf(st, sizeof(st), "%s", state);
+       info.state = st;
+       info.flags = 0;
+
+       if (sdata.updated_cb)
+               sdata.updated_cb(&info, sdata.data);
+       else
+                       _E("callback is NULL");
+
+out:
+       free(sig);
+       free(name);
+       free(state);
+}
+
+static int external_connection_register_changed_event(
+               ConnectionUpdated updated_cb, void *data)
+{
+       int ret;
+
+       if (sdata.updated_cb) {
+               _E("update callback is already registered");
+               return -EEXIST;
+       }
+
+       ret = register_dbus_signal(EXTCON_OBJECT,
+                       EXTCON_IFACE, EXTCON_SIGNAL,
+                       signal_delivered, &sdata, &id);
+       if (ret < 0) {
+               _E("Failed to register signal");
+               return -ENOMEM;
+       }
+
+       sdata.updated_cb = updated_cb;
+       sdata.data = data;
+
+       return 0;
+}
+
+static void external_connection_unregister_changed_event(
+               ConnectionUpdated updated_cb)
+{
+       unregister_dbus_signal(&id);
+       sdata.updated_cb = NULL;
+       sdata.data = NULL;
+}
+
+static int external_connection_get_current_state(
+               ConnectionUpdated updated_cb, void *data)
+{
+       int ret, i, val;
+       struct connection_info info;
+       char buf[8];
+
+       if (!updated_cb)
+               return -EINVAL;
+
+       for (i = 0 ; i < ARRAY_SIZE(extcon_devices) ; i++) {
+               ret = sys_get_int(extcon_devices[i].path, &val);
+               if (ret < 0) {
+                       _E("Failed to get value of (%s, ret:%d)",
+                                       extcon_devices[i].path, ret);
+                       continue;
+               }
+
+               info.name = extcon_devices[i].type;
+               snprintf(buf, sizeof(buf), "%d", val);
+               info.state = buf;
+
+               updated_cb(&info, data);
+       }
+
+       return 0;
+}
+
+static int external_connection_open(struct hw_info *info,
+               const char *id, struct hw_common **common)
+{
+       struct external_connection_device *external_connection_dev;
+
+       if (!info || !common)
+               return -EINVAL;
+
+       external_connection_dev = calloc(1, sizeof(struct external_connection_device));
+       if (!external_connection_dev)
+               return -ENOMEM;
+
+       external_connection_dev->common.info = info;
+       external_connection_dev->register_changed_event
+               = external_connection_register_changed_event;
+       external_connection_dev->unregister_changed_event
+               = external_connection_unregister_changed_event;
+       external_connection_dev->get_current_state
+               = external_connection_get_current_state;
+
+       *common = (struct hw_common *)external_connection_dev;
+       return 0;
+}
+
+static int external_connection_close(struct hw_common *common)
+{
+       if (!common)
+               return -EINVAL;
+
+       free(common);
+       return 0;
+}
+
+HARDWARE_MODULE_STRUCTURE = {
+       .magic = HARDWARE_INFO_TAG,
+       .hal_version = HARDWARE_INFO_VERSION,
+       .device_version = EXTERNAL_CONNECTION_HARDWARE_DEVICE_VERSION,
+       .id = EXTERNAL_CONNECTION_HARDWARE_DEVICE_ID,
+       .name = "external_connection",
+       .open = external_connection_open,
+       .close = external_connection_close,
+};
index c4fa050..e87110c 100644 (file)
@@ -11,6 +11,8 @@ BuildRequires:      cmake
 BuildRequires:      pkgconfig(dlog)
 BuildRequires:      pkgconfig(devman_plugin)
 BuildRequires:      pkgconfig(hwcommon)
+BuildRequires:      pkgconfig(glib-2.0)
+BuildRequires:      pkgconfig(gio-2.0)
 
 %description
 Emulator plugin for libdevice-node.