#include "peripheral_bus_gpio.h"
#include "peripheral_bus_i2c.h"
#include "peripheral_bus_pwm.h"
+#include "peripheral_bus_uart.h"
#include "peripheral_common.h"
gboolean handle_gpio_open(
return true;
}
+gboolean handle_uart_open(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint port,
+ gpointer user_data)
+{
+ peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle;
+
+ ret = peripheral_bus_uart_open(port, &uart_handle, user_data);
+ if (ret == PERIPHERAL_ERROR_NONE) {
+ guint pid = 0;
+ GError *error = NULL;
+ GVariant *_ret;
+ const gchar *id;
+
+ 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);
+ } else
+ g_error_free(error);
+
+ uart_handle->client_info.pid = (pid_t)pid;
+ uart_handle->client_info.pgid = getpgid(pid);
+ uart_handle->client_info.id = strdup(id);
+
+ _D("port : %d, id = %s", port, uart_handle->client_info.id);
+ }
+
+ peripheral_io_gdbus_uart_complete_open(uart, invocation, GPOINTER_TO_UINT(uart_handle), ret);
+
+ return true;
+}
+
+gboolean handle_uart_close(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_close(uart_handle, user_data);
+ }
+
+ peripheral_io_gdbus_uart_complete_close(uart, invocation, ret);
+
+ return true;
+}
+
+gboolean handle_uart_flush(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_flush(uart_handle);
+ }
+
+ peripheral_io_gdbus_uart_complete_flush(uart, invocation, ret);
+
+ return true;
+}
+
+gboolean handle_uart_set_baudrate(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ guint baudrate,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_set_baudrate(uart_handle, baudrate);
+ }
+
+ peripheral_io_gdbus_uart_complete_set_baudrate(uart, invocation, ret);
+
+ return true;
+}
+gboolean handle_uart_set_mode(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ guint byte_size,
+ guint parity,
+ guint stop_bits,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_set_mode(uart_handle, byte_size, parity, stop_bits);
+ }
+
+ peripheral_io_gdbus_uart_complete_set_mode(uart, invocation, ret);
+
+ return true;
+}
+gboolean handle_uart_set_flowcontrol(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ gboolean xonxoff,
+ gboolean rtscts,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_set_flowcontrol(uart_handle, xonxoff, rtscts);
+ }
+
+ peripheral_io_gdbus_uart_complete_set_flowcontrol(uart, invocation, ret);
+
+ return true;
+}
+
+gboolean handle_uart_read(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ gint length,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+ uint8_t err_buf[2] = {0, };
+ GVariant *data_array = NULL;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_read(uart_handle, &data_array, length);
+ }
+
+ if (!data_array)
+ data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+
+ peripheral_io_gdbus_uart_complete_read(uart, invocation, data_array, ret);
+
+ return true;
+}
+
+gboolean handle_uart_write(
+ PeripheralIoGdbusUart *uart,
+ GDBusMethodInvocation *invocation,
+ gint handle,
+ gint length,
+ GVariant *data_array,
+ gpointer user_data)
+{
+ peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+ pb_uart_data_h uart_handle = GUINT_TO_POINTER(handle);
+ const gchar *id;
+
+ /* Handle validation */
+ if (!uart_handle || !uart_handle->client_info.id) {
+ _E("uart handle is not valid");
+ ret = PERIPHERAL_ERROR_UNKNOWN;
+ } else {
+ id = g_dbus_method_invocation_get_sender(invocation);
+ if (strcmp(uart_handle->client_info.id, id)) {
+ _E("Invalid access, handle id : %s, current id : %s", uart_handle->client_info.id, id);
+ ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+ } else
+ ret = peripheral_bus_uart_write(uart_handle, data_array, length);
+ }
+
+ peripheral_io_gdbus_uart_complete_write(uart, invocation, ret);
+
+ return true;
+}
+
void peripheral_bus_emit_gpio_changed(PeripheralIoGdbusGpio *gpio,
gint pin,
gint state)
return true;
}
+static gboolean __uart_init(peripheral_bus_s *pb_data)
+{
+ GDBusObjectManagerServer *manager;
+ gboolean ret = FALSE;
+ GError *error = NULL;
+
+ /* Add interface to default object path */
+ pb_data->uart_skeleton = peripheral_io_gdbus_uart_skeleton_new();
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-open",
+ G_CALLBACK(handle_uart_open),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-close",
+ G_CALLBACK(handle_uart_close),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-flush",
+ G_CALLBACK(handle_uart_flush),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-set-baudrate",
+ G_CALLBACK(handle_uart_set_baudrate),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-set-mode",
+ G_CALLBACK(handle_uart_set_mode),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-set-flowcontrol",
+ G_CALLBACK(handle_uart_set_flowcontrol),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-read",
+ G_CALLBACK(handle_uart_read),
+ pb_data);
+ g_signal_connect(pb_data->uart_skeleton,
+ "handle-write",
+ G_CALLBACK(handle_uart_write),
+ pb_data);
+
+ manager = g_dbus_object_manager_server_new(PERIPHERAL_GDBUS_UART_PATH);
+
+ /* Set connection to 'manager' */
+ g_dbus_object_manager_server_set_connection(manager, pb_data->connection);
+
+ /* Export 'manager' interface on peripheral-io DBUS */
+ ret = g_dbus_interface_skeleton_export(
+ G_DBUS_INTERFACE_SKELETON(pb_data->uart_skeleton),
+ pb_data->connection, PERIPHERAL_GDBUS_UART_PATH, &error);
+
+ if (ret == FALSE) {
+ _E("Can not skeleton_export %s", error->message);
+ g_error_free(error);
+ }
+
+ return true;
+}
+
static void on_bus_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
if (__pwm_init(pb_data) == FALSE)
_E("Can not signal connect");
+
+ if (__uart_init(pb_data) == FALSE)
+ _E("Can not signal connect");
}
static void on_name_acquired(GDBusConnection *conn,
--- /dev/null
+/*
+ * Copyright (c) 2016-2017 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 <gio/gio.h>
+
+#include <peripheral_io.h>
+
+#include "uart.h"
+#include "peripheral_io_gdbus.h"
+#include "peripheral_bus.h"
+#include "peripheral_common.h"
+
+#define INITIAL_BUFFER_SIZE 128
+#define MAX_BUFFER_SIZE 8192
+
+GVariant *peripheral_bus_build_variant_ay(uint8_t *data, int length)
+{
+ GVariantBuilder *builder;
+ GVariant *variant;
+ int i;
+
+ if (data == NULL)
+ return NULL;
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)"));
+
+ for (i = 0; i < length; i++)
+ g_variant_builder_add(builder, "(y)", data[i]);
+
+ variant = g_variant_new("a(y)", builder);
+ g_variant_builder_unref(builder);
+
+ return variant;
+}
+
+static pb_uart_data_h peripheral_bus_uart_data_get(int port, GList **list)
+{
+ GList *uart_list = *list;
+ GList *link;
+ pb_uart_data_h uart_data;
+
+ link = uart_list;
+ while (link) {
+ uart_data = (pb_uart_data_h)link->data;
+ if (uart_data->port == port)
+ return uart_data;
+ link = g_list_next(link);
+ }
+
+ return NULL;
+}
+
+static pb_uart_data_h peripheral_bus_uart_data_new(GList **list)
+{
+ GList *uart_list = *list;
+ pb_uart_data_h uart_data;
+
+ uart_data = (pb_uart_data_h)calloc(1, sizeof(peripheral_bus_uart_data_s));
+ if (uart_data == NULL) {
+ _E("failed to allocate peripheral_bus_uart_data_s");
+ return NULL;
+ }
+
+ *list = g_list_append(uart_list, uart_data);
+
+ return uart_data;
+}
+
+static int peripheral_bus_uart_data_free(pb_uart_data_h uart_handle, GList **list)
+{
+ GList *uart_list = *list;
+ GList *link;
+ pb_uart_data_h uart_data;
+
+ link = uart_list;
+ while (link) {
+ uart_data = (pb_uart_data_h)link->data;
+
+ if (uart_data == uart_handle) {
+ *list = g_list_remove_link(uart_list, link);
+ if (uart_data->buffer)
+ free(uart_data->buffer);
+ free(uart_data);
+ g_list_free(link);
+ return 0;
+ }
+ link = g_list_next(link);
+ }
+
+ return -1;
+}
+
+int peripheral_bus_uart_open(int port, pb_uart_data_h *uart, gpointer user_data)
+{
+ peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+ pb_uart_data_h uart_handle;
+ int ret = PERIPHERAL_ERROR_NONE;
+ int fd;
+
+ if (peripheral_bus_uart_data_get(port, &pb_data->uart_list)) {
+ _E("Resource is in use, port : %d", port);
+ return PERIPHERAL_ERROR_RESOURCE_BUSY;
+ }
+
+ if ((ret = uart_open(port, &fd)) < 0)
+ return ret;
+
+ uart_handle = peripheral_bus_uart_data_new(&pb_data->uart_list);
+ if (!uart_handle)
+ return PERIPHERAL_ERROR_OUT_OF_MEMORY;
+
+ uart_handle->fd = fd;
+ uart_handle->port = port;
+
+ uart_handle->buffer = (uint8_t*)calloc(1, INITIAL_BUFFER_SIZE);
+ if (!uart_handle->buffer) {
+ _E("Failed to allocate buffer");
+ return PERIPHERAL_ERROR_OUT_OF_MEMORY;
+ }
+
+ uart_handle->buffer_size = INITIAL_BUFFER_SIZE;
+ *uart = uart_handle;
+
+ return ret;
+}
+
+int peripheral_bus_uart_close(pb_uart_data_h uart, gpointer user_data)
+{
+ peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+ int ret;
+
+ _D("uart_close, port : %d, id = %s", uart->port, uart->client_info.id);
+
+ if ((ret = uart_close(uart->fd)) < 0)
+ return ret;
+
+ if (peripheral_bus_uart_data_free(uart, &pb_data->uart_list) < 0)
+ _E("Failed to free uart data");
+
+ return ret;
+}
+
+int peripheral_bus_uart_flush(pb_uart_data_h uart)
+{
+ return uart_flush(uart->fd);
+}
+
+int peripheral_bus_uart_set_baudrate(pb_uart_data_h uart, int baudrate)
+{
+ return uart_set_baudrate(uart->fd, baudrate);
+}
+
+int peripheral_bus_uart_set_mode(pb_uart_data_h uart, int byte_size, int parity, int stop_bits)
+{
+ return uart_set_mode(uart->fd, byte_size, parity, stop_bits);
+}
+
+int peripheral_bus_uart_set_flowcontrol(pb_uart_data_h uart, bool xonxoff, bool rtscts)
+{
+ return uart_set_flowcontrol(uart->fd, xonxoff, rtscts);
+}
+
+int peripheral_bus_uart_read(pb_uart_data_h uart, GVariant **data_array, int length)
+{
+ int ret;
+
+ /* Limit maximum length */
+ if (length > MAX_BUFFER_SIZE) length = MAX_BUFFER_SIZE;
+
+ /* Increase buffer if needed */
+ if (length > uart->buffer_size) {
+ uint8_t *buffer;
+
+ buffer = (uint8_t*)realloc(uart->buffer, length);
+ RETVM_IF(buffer == NULL, PERIPHERAL_ERROR_OUT_OF_MEMORY, "Failed to realloc buffer");
+
+ uart->buffer = buffer;
+ uart->buffer_size = length;
+ }
+
+ ret = uart_read(uart->fd, uart->buffer, length);
+ if (ret > 0)
+ *data_array = peripheral_bus_build_variant_ay(uart->buffer, ret);
+
+ return ret;
+}
+
+int peripheral_bus_uart_write(pb_uart_data_h uart, GVariant *data_array, int length)
+{
+ GVariantIter *iter;
+ guchar str;
+ int i = 0;
+
+ /* Limit maximum length */
+ if (length > MAX_BUFFER_SIZE) length = MAX_BUFFER_SIZE;
+
+ /* Increase buffer if needed */
+ if (length > uart->buffer_size) {
+ uint8_t *buffer;
+
+ buffer = (uint8_t*)realloc(uart->buffer, length);
+ RETVM_IF(buffer == NULL, PERIPHERAL_ERROR_OUT_OF_MEMORY, "Failed to realloc buffer");
+
+ uart->buffer = buffer;
+ uart->buffer_size = length;
+ }
+
+ g_variant_get(data_array, "a(y)", &iter);
+ while (g_variant_iter_loop(iter, "(y)", &str) && i < length)
+ uart->buffer[i++] = str;
+ g_variant_iter_free(iter);
+
+ return uart_write(uart->fd, uart->buffer, length);
+}