* limitations under the License.
*/
+#include <assert.h>
#include <peripheral_io.h>
#include <gio/gunixfdlist.h>
#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(
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);
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);
*/
#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;
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);
}
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");
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;