Add structure to store i2c client context 27/128127/2 submit/tizen/20170508.033648
authorHyeongsik Min <hyeongsik.min@samsung.com>
Sun, 7 May 2017 09:31:29 +0000 (18:31 +0900)
committerHyeongsik Min <hyeongsik.min@samsung.com>
Mon, 8 May 2017 00:40:30 +0000 (00:40 +0000)
- Add access control based on the client's bus name.
- Change argument name and type of i2c gdbus method.

Change-Id: I2d81181b41cc35ca34c71fefcf2beb8af0bc92ce
Signed-off-by: Hyeongsik Min <hyeongsik.min@samsung.com>
src/daemon/peripheral_bus.c
src/daemon/peripheral_bus.h
src/daemon/peripheral_bus_i2c.c
src/daemon/peripheral_bus_i2c.h
src/daemon/peripheral_io.xml

index f138ae4..a73b876 100644 (file)
@@ -183,15 +183,13 @@ gboolean handle_i2c_open(
                GDBusMethodInvocation *invocation,
                gint bus,
                gint address,
-               gint fd,
                gpointer user_data)
 {
        peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
-       struct _peripheral_i2c_s st_i2c;
+       pb_i2c_data_h i2c_handle;
 
-       // TODO: Create i2c instance
-       ret = peripheral_bus_i2c_open(&st_i2c, bus, address);
-       peripheral_io_gdbus_i2c_complete_open(i2c, invocation, st_i2c.fd, ret);
+       ret = peripheral_bus_i2c_open(invocation, bus, address, &i2c_handle, user_data);
+       peripheral_io_gdbus_i2c_complete_open(i2c, invocation, GPOINTER_TO_UINT(i2c_handle), ret);
 
        return true;
 }
@@ -199,15 +197,13 @@ gboolean handle_i2c_open(
 gboolean handle_i2c_close(
                PeripheralIoGdbusI2c *i2c,
                GDBusMethodInvocation *invocation,
-               gint fd,
+               gint handle,
                gpointer user_data)
 {
        peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
-       struct _peripheral_i2c_s st_i2c;
+       pb_i2c_data_h i2c_handle = GUINT_TO_POINTER(handle);
 
-       st_i2c.fd = fd;
-
-       ret = peripheral_bus_i2c_close(&st_i2c);
+       ret = peripheral_bus_i2c_close(invocation, i2c_handle, user_data);
        peripheral_io_gdbus_i2c_complete_close(i2c, invocation, ret);
 
        return true;
@@ -216,20 +212,19 @@ gboolean handle_i2c_close(
 gboolean handle_i2c_read(
                PeripheralIoGdbusI2c *i2c,
                GDBusMethodInvocation *invocation,
-               gint fd,
+               gint handle,
                gint length,
                gpointer user_data)
 {
        peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
-       struct _peripheral_i2c_s st_i2c;
+       pb_i2c_data_h i2c_handle = GUINT_TO_POINTER(handle);
        // TODO: Fix size of data buffer
        unsigned char data[128];
        GVariantBuilder *builder;
        GVariant *data_array;
        int i = 0;
 
-       st_i2c.fd = fd;
-       ret = peripheral_bus_i2c_read(&st_i2c, length, data);
+       ret = peripheral_bus_i2c_read(invocation, i2c_handle, length, data, user_data);
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)"));
 
@@ -247,20 +242,19 @@ gboolean handle_i2c_read(
 gboolean handle_i2c_write(
                PeripheralIoGdbusI2c *i2c,
                GDBusMethodInvocation *invocation,
-               gint fd,
+               gint handle,
                gint length,
                GVariant *data_array,
                gpointer user_data)
 {
        peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
-       struct _peripheral_i2c_s st_i2c;
+       pb_i2c_data_h i2c_handle = GUINT_TO_POINTER(handle);
        // TODO: Fix size of data buffer
        unsigned char data[128];
        GVariantIter *iter;
        guchar str;
        int i = 0;
 
-       st_i2c.fd = fd;
        g_variant_get(data_array, "a(y)", &iter);
        while (g_variant_iter_loop(iter, "(y)", &str)) {
                data[i++] = str;
@@ -268,7 +262,7 @@ gboolean handle_i2c_write(
        }
        g_variant_iter_free(iter);
 
-       ret = peripheral_bus_i2c_write(&st_i2c, length, (unsigned char*)data);
+       ret = peripheral_bus_i2c_write(invocation, i2c_handle, length, (unsigned char*)data, user_data);
        peripheral_io_gdbus_i2c_complete_write(i2c, invocation, ret);
 
        return true;
@@ -498,19 +492,19 @@ static gboolean __i2c_init(peripheral_bus_s *pb_data)
        g_signal_connect(pb_data->i2c_skeleton,
                        "handle-open",
                        G_CALLBACK(handle_i2c_open),
-                       NULL);
+                       pb_data);
        g_signal_connect(pb_data->i2c_skeleton,
                        "handle-close",
                        G_CALLBACK(handle_i2c_close),
-                       NULL);
+                       pb_data);
        g_signal_connect(pb_data->i2c_skeleton,
                        "handle-read",
                        G_CALLBACK(handle_i2c_read),
-                       NULL);
+                       pb_data);
        g_signal_connect(pb_data->i2c_skeleton,
                        "handle-write",
                        G_CALLBACK(handle_i2c_write),
-                       NULL);
+                       pb_data);
 
        manager = g_dbus_object_manager_server_new(PERIPHERAL_DBUS_I2C_PATH);
 
index c8f1af0..73df3d8 100644 (file)
 
 #include <gio/gio.h>
 
+#include "peripheral_io_gdbus.h"
+
 typedef struct {
        /* daemon variable */
        /* devices */
        GList *gpio_list;
+       GList *i2c_list;
        /* gdbus variable */
        guint reg_id;
        GDBusConnection *connection;
@@ -32,6 +35,12 @@ typedef struct {
 } peripheral_bus_s;
 
 typedef struct {
+       char *id;
+       pid_t pid;
+       pid_t pgid;
+} pb_client_info_s;
+
+typedef struct {
        /* gpio info */
        int pin;
        int direction;
@@ -45,7 +54,16 @@ typedef struct {
        PeripheralIoGdbusGpio *gpio_skeleton;
 } peripheral_bus_gpio_data_s;
 
-typedef peripheral_bus_gpio_data_s * pb_gpio_data_h;
+typedef struct {
+       int bus;
+       int address;
+       int fd;
+       /* client info */
+       pb_client_info_s *client_info;
+} peripheral_bus_i2c_data_s;
+
+typedef peripheral_bus_gpio_data_s *pb_gpio_data_h;
+typedef peripheral_bus_i2c_data_s *pb_i2c_data_h;
 
 void peripheral_bus_emit_gpio_changed(PeripheralIoGdbusGpio *gpio,
                                                                        gint pin,
index f2c8bca..f252c9e 100644 (file)
 #include <gio/gio.h>
 
 #include <peripheral_io.h>
-#include <peripheral_internal.h>
 
 #include "i2c.h"
+#include "peripheral_bus.h"
 #include "peripheral_common.h"
 
-int peripheral_bus_i2c_open(peripheral_i2c_h i2c, int bus, int address)
+static pb_client_info_s* peripheral_bus_i2c_get_client_info(GDBusMethodInvocation *invocation, peripheral_bus_s *pb_data)
 {
+       pb_client_info_s *client_info;
+       guint pid = 0;
+       GError *error = NULL;
+       GVariant *_ret;
+       const gchar *id;
+
+       client_info = (pb_client_info_s*)calloc(1, sizeof(pb_client_info_s));
+
+       id = g_dbus_method_invocation_get_sender(invocation);
+
+       _ret = g_dbus_connection_call_sync(pb_data->connection,
+               "org.freedesktop.DBus",
+               "/org/freedesktop/DBus",
+               "org.freedesktop.DBus",
+               "GetConnectionUnixProcessID",
+               g_variant_new("(s)", id),
+               NULL,
+               G_DBUS_CALL_FLAGS_NONE,
+               -1,
+               NULL,
+               &error);
+
+       if (_ret != NULL) {
+               g_variant_get(_ret, "(u)", &pid);
+               g_variant_unref(_ret);
+       }
+       g_error_free(error);
+
+       client_info->pid = (pid_t)pid;
+       client_info->pgid = getpgid(pid);
+       client_info->id = strdup(id);
+
+       return client_info;
+}
+
+static pb_i2c_data_h peripheral_bus_i2c_data_get(int bus, int address, GList **list)
+{
+       GList *i2c_list = *list;
+       GList *link;
+       pb_i2c_data_h i2c_data;
+
+       if (i2c_list == NULL)
+               return NULL;
+
+       link = i2c_list;
+       while (link) {
+               i2c_data = (pb_i2c_data_h)link->data;
+               if (i2c_data->bus == bus && i2c_data->address == address)
+                       return i2c_data;
+               link = g_list_next(link);
+       }
+
+       return NULL;
+}
+
+static pb_i2c_data_h peripheral_bus_i2c_data_new(GList **list)
+{
+       GList *i2c_list = *list;
+       pb_i2c_data_h i2c_data;
+
+       i2c_data = (pb_i2c_data_h)calloc(1, sizeof(peripheral_bus_i2c_data_s));
+       if (i2c_data == NULL) {
+               _E("failed to allocate peripheral_bus_i2c_data_s");
+               return NULL;
+       }
+
+       *list = g_list_append(i2c_list, i2c_data);
+
+       return i2c_data;
+}
+
+static int peripheral_bus_i2c_data_free(pb_i2c_data_h i2c_handle, GList **list)
+{
+       GList *i2c_list = *list;
+       GList *link;
+       pb_i2c_data_h i2c_data;
+
+       if (i2c_list == NULL)
+               return -1;
+
+       link = i2c_list;
+       while (link) {
+               i2c_data = (pb_i2c_data_h)link->data;
+
+               if (i2c_data == i2c_handle) {
+                       *list = g_list_remove_link(i2c_list, link);
+                       if (i2c_data->client_info) {
+                               free(i2c_data->client_info->id);
+                               free(i2c_data->client_info);
+                       }
+                       free(i2c_data);
+                       g_list_free(link);
+                       return 0;
+               }
+               link = g_list_next(link);
+       }
+
+       return -1;
+}
+
+int peripheral_bus_i2c_open(GDBusMethodInvocation *invocation, int bus, int address, pb_i2c_data_h *i2c, gpointer user_data)
+{
+       peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+       pb_i2c_data_h i2c_handle;
        int ret;
+       int fd;
+
+       if (peripheral_bus_i2c_data_get(bus, address, &pb_data->i2c_list)) {
+               _E("Resource is in use, bus : %d, address : %d", bus, address);
+               return PERIPHERAL_ERROR_RESOURCE_BUSY;
+       }
+
+       if ((ret = i2c_open(bus, &fd)) < 0)
+               return ret;
 
-       if ((ret = i2c_open(bus, &i2c->fd)) < 0)
+       if ((ret = i2c_set_address(fd, address)) < 0) {
+               i2c_close(fd);
                return ret;
+       }
+
+       i2c_handle = peripheral_bus_i2c_data_new(&pb_data->i2c_list);
+
+       i2c_handle->fd = fd;
+       i2c_handle->bus = bus;
+       i2c_handle->address = address;
+       i2c_handle->client_info = peripheral_bus_i2c_get_client_info(invocation, pb_data);
+       *i2c = i2c_handle;
 
-       return i2c_set_address(i2c->fd, address);
+       _D("bus : %d, address : %d, pgid = %d, id = %s", bus, address,
+               i2c_handle->client_info->pgid,
+               i2c_handle->client_info->id);
+
+       return ret;
 }
 
-int peripheral_bus_i2c_read(peripheral_i2c_h i2c, int length, unsigned char * data)
+int peripheral_bus_i2c_read(GDBusMethodInvocation *invocation, pb_i2c_data_h i2c, int length, unsigned char *data, gpointer user_data)
 {
+       const gchar *id;
+
+       id = g_dbus_method_invocation_get_sender(invocation);
+
+       if (strcmp(i2c->client_info->id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", i2c->client_info->id, id);
+               return PERIPHERAL_ERROR_INVALID_OPERATION;
+       }
+
        return i2c_read(i2c->fd, data, length);
 }
 
-int peripheral_bus_i2c_write(peripheral_i2c_h i2c, int length, unsigned char * data)
+int peripheral_bus_i2c_write(GDBusMethodInvocation *invocation, pb_i2c_data_h i2c, int length, unsigned char *data, gpointer user_data)
 {
+       const gchar *id;
+
+       id = g_dbus_method_invocation_get_sender(invocation);
+
+       if (strcmp(i2c->client_info->id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", i2c->client_info->id, id);
+               return PERIPHERAL_ERROR_INVALID_OPERATION;
+       }
+
        return i2c_write(i2c->fd, data, length);
 }
 
-int peripheral_bus_i2c_close(peripheral_i2c_h i2c)
+int peripheral_bus_i2c_close(GDBusMethodInvocation *invocation, pb_i2c_data_h i2c, gpointer user_data)
 {
-       return i2c_close(i2c->fd);
+       peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+       const gchar *id;
+       int ret;
+
+       _D("i2c_close, bus : %d, address : %d, pgid = %d", i2c->bus, i2c->address, i2c->client_info->pgid);
+
+       id = g_dbus_method_invocation_get_sender(invocation);
+
+       if (strcmp(i2c->client_info->id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", i2c->client_info->id, id);
+               return PERIPHERAL_ERROR_INVALID_OPERATION;
+       }
+
+       if ((ret = i2c_close(i2c->fd)) < 0)
+               return ret;
+
+       if (peripheral_bus_i2c_data_free(i2c, &pb_data->i2c_list) < 0)
+               _E("Failed to free i2c data");
+
+       return ret;
 }
index 87b1ed3..6865ce7 100644 (file)
 #ifndef __PERIPHERAL_BUS_I2C_H__
 #define __PERIPHERAL_BUS_I2C_H__
 
-int peripheral_bus_i2c_open(peripheral_i2c_h i2c, int bus, int address);
-int peripheral_bus_i2c_set_address(peripheral_i2c_h i2c, int address);
-int peripheral_bus_i2c_read(peripheral_i2c_h i2c, int length, unsigned char * data);
-int peripheral_bus_i2c_write(peripheral_i2c_h i2c, int length, unsigned char * data);
-int peripheral_bus_i2c_close(peripheral_i2c_h i2c);
+int peripheral_bus_i2c_open(GDBusMethodInvocation *invocation, int bus, int address, pb_i2c_data_h *i2c, gpointer user_data);
+int peripheral_bus_i2c_read(GDBusMethodInvocation *invocation, pb_i2c_data_h i2c, int length, unsigned char *data, gpointer user_data);
+int peripheral_bus_i2c_write(GDBusMethodInvocation *invocation, pb_i2c_data_h i2c, int length, unsigned char *data, gpointer user_data);
+int peripheral_bus_i2c_close(GDBusMethodInvocation *invocation, pb_i2c_data_h i2c, gpointer user_data);
 
 #endif /* __PERIPHERAL_BUS_I2C_H__ */
index ed9559c..ba2edef 100644 (file)
                <method name="Open">
                        <arg type="i" name="bus" direction="in"/>
                        <arg type="i" name="address" direction="in"/>
-                       <arg type="i" name="fd" direction="out"/>
+                       <arg type="u" name="handle" direction="out"/>
                        <arg type="i" name="result" direction="out"/>
                </method>
                <method name="Close">
-                       <arg type="i" name="fd" direction="in"/>
+                       <arg type="u" name="handle" direction="in"/>
                        <arg type="i" name="result" direction="out"/>
                </method>
                <method name="Read">
-                       <arg type="i" name="fd" direction="in"/>
+                       <arg type="u" name="handle" direction="in"/>
                        <arg type="i" name="length" direction="in"/>
                        <arg type="a(y)" name="data" direction="out">
                                <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>
@@ -74,7 +74,7 @@
                        <arg type="i" name="result" direction="out"/>
                </method>
                <method name="Write">
-                       <arg type="i" name="fd" direction="in"/>
+                       <arg type="u" name="handle" direction="in"/>
                        <arg type="i" name="length" direction="in"/>
                        <arg type="a(y)" name="data" direction="in">
                                <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>