summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarol Lewandowski <k.lewandowsk@samsung.com>2021-06-02 18:38:50 +0200
committerKarol Lewandowski <k.lewandowsk@samsung.com>2021-06-04 12:01:46 +0200
commit0b98b4f2b50c32f9a76dc90bdf948cf5557795e0 (patch)
tree4e06b7776f0481f301d07ac8c1122a3308aa1f7e
parent4721fc8057fb0f937e94533e00804a03cbe01366 (diff)
downloadperipheral-bus-tizen.tar.gz
peripheral-bus-tizen.tar.bz2
peripheral-bus-tizen.zip
Change-Id: I1d0672d682cd4dc5b69eaa80546c04a87c61285e
-rw-r--r--include/gdbus/peripheral_gdbus_i2c.h9
-rw-r--r--include/handle/peripheral_handle.h6
-rw-r--r--include/handle/peripheral_handle_i2c.h2
-rw-r--r--packaging/peripheral-bus.spec2
-rw-r--r--src/gdbus/peripheral_gdbus_i2c.c151
-rw-r--r--src/gdbus/peripheral_io.xml8
-rw-r--r--src/handle/peripheral_handle_i2c.c38
-rw-r--r--src/peripheral_bus.c4
8 files changed, 184 insertions, 36 deletions
diff --git a/include/gdbus/peripheral_gdbus_i2c.h b/include/gdbus/peripheral_gdbus_i2c.h
index 6fb3813..4c4878c 100644
--- a/include/gdbus/peripheral_gdbus_i2c.h
+++ b/include/gdbus/peripheral_gdbus_i2c.h
@@ -27,6 +27,15 @@ gboolean peripheral_gdbus_i2c_open(
gint address,
gpointer user_data);
+gboolean peripheral_gdbus_i2c_open_flags(
+ PeripheralIoGdbusI2c *i2c,
+ GDBusMethodInvocation *invocation,
+ GUnixFDList *fd_list,
+ gint bus,
+ gint address,
+ gint flags,
+ gpointer user_data);
+
gboolean peripheral_gdbus_i2c_close(
PeripheralIoGdbusI2c *i2c,
GDBusMethodInvocation *invocation,
diff --git a/include/handle/peripheral_handle.h b/include/handle/peripheral_handle.h
index 66e1269..879c148 100644
--- a/include/handle/peripheral_handle.h
+++ b/include/handle/peripheral_handle.h
@@ -75,8 +75,12 @@ typedef struct {
} peripheral_handle_spi_s;
typedef struct {
- uint watch_id;
uint32_t handle_id;
+ uint watch_id;
+
+ peripheral_open_flags_e open_flags; // used by i2c only for now
+ GList *watch_list; // ditto
+
GList **list;
union {
peripheral_handle_gpio_s gpio;
diff --git a/include/handle/peripheral_handle_i2c.h b/include/handle/peripheral_handle_i2c.h
index 55079e0..ae89911 100644
--- a/include/handle/peripheral_handle_i2c.h
+++ b/include/handle/peripheral_handle_i2c.h
@@ -17,7 +17,7 @@
#ifndef __PERIPHERAL_HANDLE_I2C_H__
#define __PERIPHERAL_HANDLE_I2C_H__
-int peripheral_handle_i2c_create(int bus, int address, peripheral_h *handle, gpointer user_data);
+int peripheral_handle_i2c_create(int bus, int address, int flags, peripheral_h *handle, gpointer user_data);
int peripheral_handle_i2c_destroy(peripheral_h handle);
#endif /* __PERIPHERAL_HANDLE_I2C_H__ */
diff --git a/packaging/peripheral-bus.spec b/packaging/peripheral-bus.spec
index 37dfc30..41afbe3 100644
--- a/packaging/peripheral-bus.spec
+++ b/packaging/peripheral-bus.spec
@@ -1,6 +1,6 @@
Name: peripheral-bus
Summary: Tizen Peripheral Input & Output Service Daemon
-Version: 0.1.4
+Version: 0.2.0
Release: 0
Group: System & System Tools
License: Apache-2.0
diff --git a/src/gdbus/peripheral_gdbus_i2c.c b/src/gdbus/peripheral_gdbus_i2c.c
index 7003f37..5fbe6df 100644
--- a/src/gdbus/peripheral_gdbus_i2c.c
+++ b/src/gdbus/peripheral_gdbus_i2c.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <assert.h>
#include <peripheral_io.h>
#include <gio/gunixfdlist.h>
@@ -25,20 +26,82 @@
#include "peripheral_interface_i2c.h"
#include "peripheral_gdbus_i2c.h"
+struct watch_data {
+ guint watch_id;
+ peripheral_h handle;
+ char *name;
+};
+
+static void __watch_remove_one(struct watch_data *watch_ptr)
+{
+ assert(watch_ptr);
+ peripheral_h i2c_handle = watch_ptr->handle;
+ assert(i2c_handle);
+
+ g_bus_unwatch_name(watch_ptr->watch_id);
+ i2c_handle->watch_list = g_list_remove(i2c_handle->watch_list, watch_ptr);
+
+ free(watch_ptr->name);
+ free(watch_ptr);
+}
+
+static int __watch_remove(struct watch_data *watch_ptr)
+{
+ assert(watch_ptr);
+ peripheral_h i2c_handle = watch_ptr->handle;
+ assert(i2c_handle);
+
+ int ret = PERIPHERAL_ERROR_NONE;
+
+ __watch_remove_one(watch_ptr);
+
+ if (!i2c_handle->watch_list) {
+ _D("Removed last referenced i2c client, dropping handle");
+
+ ret = peripheral_handle_i2c_destroy(i2c_handle);
+ if (ret != PERIPHERAL_ERROR_NONE)
+ _E("Failed to destroy i2c handle");
+ } else
+ _D("Remaining %u client(s) for i2c handle remaining, keeping it for now", g_list_length(i2c_handle->watch_list));
+
+ return ret;
+}
+
static void __i2c_on_name_vanished(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
- int ret = PERIPHERAL_ERROR_NONE;
-
- peripheral_h i2c_handle = (peripheral_h)user_data;
_D("appid [%s] vanished ", name);
+ (void)__watch_remove((struct watch_data *)user_data);
+}
+
+static bool __do_watch(GDBusMethodInvocation *invocation, peripheral_h i2c_handle)
+{
+ assert(invocation);
+ assert(i2c_handle);
+
+ char *name = strdup(g_dbus_method_invocation_get_sender(invocation));
+ if (!name)
+ return false;
- g_bus_unwatch_name(i2c_handle->watch_id);
+ struct watch_data *watch_ptr = malloc(sizeof(struct watch_data));
+ if (!watch_ptr) {
+ free(name);
+ return false;
+ }
+
+ watch_ptr->name = name;
+ watch_ptr->handle = i2c_handle;
+ watch_ptr->watch_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
+ name,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ NULL,
+ __i2c_on_name_vanished,
+ watch_ptr,
+ NULL);
+ i2c_handle->watch_list = g_list_append(i2c_handle->watch_list, watch_ptr);
- ret = peripheral_handle_i2c_destroy(i2c_handle);
- if (ret != PERIPHERAL_ERROR_NONE)
- _E("Failed to destroy i2c handle");
+ return true;
}
gboolean peripheral_gdbus_i2c_open(
@@ -68,20 +131,57 @@ gboolean peripheral_gdbus_i2c_open(
goto out;
}
- ret = peripheral_handle_i2c_create(bus, address, &i2c_handle, user_data);
+ ret = peripheral_handle_i2c_create(bus, address, PERIPHERAL_OPEN_FLAGS_PRIVATE, &i2c_handle, user_data);
if (ret != PERIPHERAL_ERROR_NONE) {
_E("Failed to create i2c handle");
goto out;
}
- i2c_handle->watch_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
- g_dbus_method_invocation_get_sender(invocation),
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- NULL,
- __i2c_on_name_vanished,
- i2c_handle,
- NULL);
+ if (!__do_watch(invocation, i2c_handle))
+ goto out;
+out:
+ peripheral_io_gdbus_i2c_complete_open(i2c, invocation, i2c_fd_list, PERIPHERAL_H_TO_ID(i2c_handle), ret);
+ peripheral_interface_i2c_fd_list_destroy(i2c_fd_list);
+
+ return true;
+}
+
+gboolean peripheral_gdbus_i2c_open_flags(
+ PeripheralIoGdbusI2c *i2c,
+ GDBusMethodInvocation *invocation,
+ GUnixFDList *fd_list,
+ gint bus,
+ gint address,
+ gint flags,
+ gpointer user_data)
+{
+ int ret = PERIPHERAL_ERROR_NONE;
+
+ peripheral_info_s *info = (peripheral_info_s*)user_data;
+ peripheral_h i2c_handle = NULL;
+ GUnixFDList *i2c_fd_list = NULL;
+
+ ret = peripheral_privilege_check(invocation, info->connection);
+ if (ret != 0) {
+ _E("Permission denied.");
+ ret = PERIPHERAL_ERROR_PERMISSION_DENIED;
+ goto out;
+ }
+
+ ret = peripheral_interface_i2c_fd_list_create(bus, address, &i2c_fd_list);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("Failed to create i2c fd list");
+ goto out;
+ }
+ ret = peripheral_handle_i2c_create(bus, address, flags, &i2c_handle, user_data);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("Failed to create i2c handle");
+ goto out;
+ }
+
+ if (!__do_watch(invocation, i2c_handle))
+ goto out;
out:
peripheral_io_gdbus_i2c_complete_open(i2c, invocation, i2c_fd_list, PERIPHERAL_H_TO_ID(i2c_handle), ret);
peripheral_interface_i2c_fd_list_destroy(i2c_fd_list);
@@ -105,12 +205,21 @@ gboolean peripheral_gdbus_i2c_close(
goto out;
}
- g_bus_unwatch_name(i2c_handle->watch_id);
-
- ret = peripheral_handle_i2c_destroy(i2c_handle);
- if (ret != PERIPHERAL_ERROR_NONE)
- _E("Failed to destroy i2c handle");
-
+ const char *name = g_dbus_method_invocation_get_sender(invocation);
+ struct watch_data *found = NULL;
+ for (GList *list = i2c_handle->watch_list; list; list = g_list_next(list)) {
+ struct watch_data *ptr = (struct watch_data *)list->data;
+ if (!strcmp(name, ptr->name)) {
+ found = ptr;
+ break;
+ }
+ }
+ if (found)
+ ret = __watch_remove(found);
+ else {
+ ret = PERIPHERAL_ERROR_INVALID_PARAMETER;
+ _E("i2c close called but referenced client not found");
+ }
out:
peripheral_io_gdbus_i2c_complete_close(i2c, invocation, ret);
diff --git a/src/gdbus/peripheral_io.xml b/src/gdbus/peripheral_io.xml
index db72361..c868cdf 100644
--- a/src/gdbus/peripheral_io.xml
+++ b/src/gdbus/peripheral_io.xml
@@ -20,6 +20,14 @@
<arg type="u" name="handle" direction="out"/>
<arg type="i" name="result" direction="out"/>
</method>
+ <method name="OpenFlags">
+ <annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
+ <arg type="i" name="bus" direction="in"/>
+ <arg type="i" name="address" direction="in"/>
+ <arg type="i" name="flags" direction="in"/>
+ <arg type="u" name="handle" direction="out"/>
+ <arg type="i" name="result" direction="out"/>
+ </method>
<method name="Close">
<arg type="u" name="handle" direction="in"/>
<arg type="i" name="result" direction="out"/>
diff --git a/src/handle/peripheral_handle_i2c.c b/src/handle/peripheral_handle_i2c.c
index 8bce082..9c2a8ea 100644
--- a/src/handle/peripheral_handle_i2c.c
+++ b/src/handle/peripheral_handle_i2c.c
@@ -15,8 +15,9 @@
*/
#include "peripheral_handle.h"
+#include "peripheral_io.h"
-static bool __peripheral_handle_i2c_is_creatable(int bus, int address, peripheral_info_s *info)
+static bool __peripheral_handle_i2c_is_creatable(int bus, int address, peripheral_info_s *info, int flags, peripheral_h *out_handle)
{
pb_board_dev_s *i2c = NULL;
peripheral_h handle;
@@ -35,8 +36,13 @@ static bool __peripheral_handle_i2c_is_creatable(int bus, int address, periphera
while (link) {
handle = (peripheral_h)link->data;
if (handle->type.i2c.bus == bus && handle->type.i2c.address == address) {
- _E("Resource is in use, bus : %d, address : %d", bus, address);
- return false;
+ if (handle->open_flags != PERIPHERAL_OPEN_FLAGS_SHARED || flags != PERIPHERAL_OPEN_FLAGS_SHARED) {
+ _E("Resource is in use, bus : %d, address : %d", bus, address);
+ return false;
+ } else {
+ *out_handle = handle;
+ return true;
+ }
}
link = g_list_next(link);
}
@@ -57,7 +63,7 @@ int peripheral_handle_i2c_destroy(peripheral_h handle)
return ret;
}
-int peripheral_handle_i2c_create(int bus, int address, peripheral_h *handle, gpointer user_data)
+int peripheral_handle_i2c_create(int bus, int address, int flags, peripheral_h *handle, gpointer user_data)
{
RETVM_IF(bus < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid i2c bus");
RETVM_IF(address < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid i2c address");
@@ -65,25 +71,33 @@ int peripheral_handle_i2c_create(int bus, int address, peripheral_h *handle, gpo
peripheral_info_s *info = (peripheral_info_s*)user_data;
+ if (flags != PERIPHERAL_OPEN_FLAGS_PRIVATE && flags != PERIPHERAL_OPEN_FLAGS_SHARED) {
+ _E("Invalid open flags passed");
+ return false;
+ }
+
peripheral_h i2c_handle = NULL;
bool is_handle_creatable = false;
- is_handle_creatable = __peripheral_handle_i2c_is_creatable(bus, address, info);
+ is_handle_creatable = __peripheral_handle_i2c_is_creatable(bus, address, info, flags, &i2c_handle);
if (is_handle_creatable == false) {
_E("bus : %d, address : 0x%x is not available", bus, address);
return PERIPHERAL_ERROR_RESOURCE_BUSY;
}
- i2c_handle = peripheral_handle_new(&info->i2c_list);
if (i2c_handle == NULL) {
- _E("peripheral_handle_new error");
- return PERIPHERAL_ERROR_OUT_OF_MEMORY;
+ i2c_handle = peripheral_handle_new(&info->i2c_list);
+ if (i2c_handle == NULL) {
+ _E("peripheral_handle_new error");
+ return PERIPHERAL_ERROR_OUT_OF_MEMORY;
+ }
+ i2c_handle->list = &info->i2c_list;
+ i2c_handle->type.i2c.bus = bus;
+ i2c_handle->type.i2c.address = address;
+ i2c_handle->open_flags = flags;
+ i2c_handle->watch_list = NULL;
}
- i2c_handle->list = &info->i2c_list;
- i2c_handle->type.i2c.bus = bus;
- i2c_handle->type.i2c.address = address;
-
*handle = i2c_handle;
return PERIPHERAL_ERROR_NONE;
diff --git a/src/peripheral_bus.c b/src/peripheral_bus.c
index 53a6379..8392421 100644
--- a/src/peripheral_bus.c
+++ b/src/peripheral_bus.c
@@ -90,6 +90,10 @@ static gboolean __i2c_init(peripheral_info_s *info)
G_CALLBACK(peripheral_gdbus_i2c_open),
info);
g_signal_connect(info->i2c_skeleton,
+ "handle-open-flags",
+ G_CALLBACK(peripheral_gdbus_i2c_open_flags),
+ info);
+ g_signal_connect(info->i2c_skeleton,
"handle-close",
G_CALLBACK(peripheral_gdbus_i2c_close),
info);