Add functions for the spi device 08/131108/9
authorjino.cho <jino.cho@samsung.com>
Thu, 25 May 2017 10:53:53 +0000 (19:53 +0900)
committerjino.cho <jino.cho@samsung.com>
Thu, 1 Jun 2017 01:52:26 +0000 (10:52 +0900)
This patch support the spi device. And, it should work properly
if the patch for peripheral-io is applied together.

Change-Id: Ib794a51e68aed07235ab423ec86f137715bc9ad9
Signed-off-by: jino.cho <jino.cho@samsung.com>
CMakeLists.txt
src/daemon/peripheral_bus.c
src/daemon/peripheral_bus.h
src/daemon/peripheral_bus_spi.c [new file with mode: 0644]
src/daemon/peripheral_bus_spi.h [new file with mode: 0644]
src/daemon/peripheral_io.xml
src/interface/include/spi.h
src/interface/spi.c

index 2d4a846..f0ed98b 100644 (file)
@@ -26,12 +26,14 @@ SET(SRCS
        src/daemon/peripheral_bus_i2c.c
        src/daemon/peripheral_bus_gpio.c
        src/daemon/peripheral_bus_uart.c
+       src/daemon/peripheral_bus_spi.c
        src/daemon/peripheral_io_gdbus.c
        src/interface/adc.c
        src/interface/gpio.c
        src/interface/i2c.c
        src/interface/pwm.c
-       src/interface/uart.c)
+       src/interface/uart.c
+       src/interface/spi.c)
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(pbus_pkgs REQUIRED ${dependents})
index 6d350e9..08c4d0e 100644 (file)
@@ -28,6 +28,7 @@
 #include "peripheral_bus_i2c.h"
 #include "peripheral_bus_pwm.h"
 #include "peripheral_bus_uart.h"
+#include "peripheral_bus_spi.h"
 #include "peripheral_common.h"
 #include "peripheral_bus_util.h"
 
@@ -76,6 +77,17 @@ static void __uart_on_name_vanished(GDBusConnection *connection,
        peripheral_bus_uart_close(uart_handle);
 }
 
+static void __spi_on_name_vanished(GDBusConnection *connection,
+               const gchar     *name,
+               gpointer         user_data)
+{
+       pb_spi_data_h spi_handle = (pb_spi_data_h)user_data;
+       _D("appid [%s] vanished ", name);
+
+       g_bus_unwatch_name(spi_handle->watch_id);
+       peripheral_bus_spi_close(spi_handle);
+}
+
 gboolean handle_gpio_open(
                PeripheralIoGdbusGpio *gpio,
                GDBusMethodInvocation *invocation,
@@ -945,6 +957,432 @@ gboolean handle_uart_write(
        return true;
 }
 
+gboolean handle_spi_open(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint bus,
+               gint cs,
+               gpointer user_data)
+{
+       peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle;
+
+       ret = peripheral_bus_spi_open(bus, cs, &spi_handle, user_data);
+       if (ret == PERIPHERAL_ERROR_NONE) {
+               if (peripheral_bus_get_client_info(invocation, pb_data, &spi_handle->client_info) == 0)
+                       _D("bus : %d, cs : %d, id = %s", bus, cs, spi_handle->client_info.id);
+               else
+                       ret = PERIPHERAL_ERROR_UNKNOWN;
+       }
+
+       spi_handle->watch_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM ,
+                       spi_handle->client_info.id,
+                       G_BUS_NAME_WATCHER_FLAGS_NONE ,
+                       NULL,
+                       __spi_on_name_vanished,
+                       spi_handle,
+                       NULL);
+
+       peripheral_io_gdbus_spi_complete_open(spi, invocation, GPOINTER_TO_UINT(spi_handle), ret);
+
+       return true;
+}
+
+gboolean handle_spi_close(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       g_bus_unwatch_name(spi_handle->watch_id);
+       ret = peripheral_bus_spi_close(spi_handle);
+
+out:
+       peripheral_io_gdbus_spi_complete_close(spi, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_spi_set_mode(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               guchar mode,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_set_mode(spi_handle, mode);
+
+out:
+       peripheral_io_gdbus_spi_complete_set_mode(spi, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_spi_get_mode(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+       uint8_t mode = 0;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_get_mode(spi_handle, &mode);
+
+out:
+       peripheral_io_gdbus_spi_complete_get_mode(spi, invocation, mode, ret);
+
+       return true;
+}
+
+gboolean handle_spi_set_lsb_first(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gboolean lsb,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_set_lsb_first(spi_handle, lsb);
+
+out:
+       peripheral_io_gdbus_spi_complete_set_lsb_first(spi, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_spi_get_lsb_first(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+       gboolean lsb = 0;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_get_lsb_first(spi_handle, &lsb);
+
+out:
+       peripheral_io_gdbus_spi_complete_get_lsb_first(spi, invocation, lsb, ret);
+
+       return true;
+}
+
+gboolean handle_spi_set_bits(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               guchar bits,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_set_bits(spi_handle, bits);
+
+out:
+       peripheral_io_gdbus_spi_complete_set_bits(spi, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_spi_get_bits(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+       uint8_t bits = 0;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_get_bits(spi_handle, &bits);
+
+out:
+       peripheral_io_gdbus_spi_complete_get_bits(spi, invocation, bits, ret);
+
+       return true;
+}
+
+gboolean handle_spi_set_frequency(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               guint freq,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_set_frequency(spi_handle, freq);
+
+out:
+       peripheral_io_gdbus_spi_complete_set_frequency(spi, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_spi_get_frequency(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+       unsigned int freq = 0;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_get_frequency(spi_handle, &freq);
+
+out:
+       peripheral_io_gdbus_spi_complete_get_frequency(spi, invocation, freq, ret);
+
+       return true;
+}
+
+gboolean handle_spi_read(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gint length,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       GVariant *data_array = NULL;
+       uint8_t err_buf[2] = {0, };
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_read(spi_handle, &data_array, length);
+
+out:
+       peripheral_io_gdbus_spi_complete_read(spi, invocation, data_array, ret);
+
+       return true;
+}
+
+gboolean handle_spi_write(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gint length,
+               GVariant *data_array,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_write(spi_handle, data_array, length);
+
+out:
+       peripheral_io_gdbus_spi_complete_write(spi, invocation, ret);
+
+       return true;
+}
+
+gboolean handle_spi_read_write(
+               PeripheralIoGdbusSpi *spi,
+               GDBusMethodInvocation *invocation,
+               gint handle,
+               gint length,
+               GVariant *tx_data_array,
+               gpointer user_data)
+{
+       peripheral_error_e ret = PERIPHERAL_ERROR_NONE;
+       pb_spi_data_h spi_handle = GUINT_TO_POINTER(handle);
+       GVariant *rx_data_array = NULL;
+       uint8_t err_buf[2] = {0, };
+       const gchar *id;
+
+       /* Handle validation */
+       if (!spi_handle || !spi_handle->client_info.id) {
+               _E("spi handle is not valid");
+               rx_data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+               ret = PERIPHERAL_ERROR_UNKNOWN;
+               goto out;
+       }
+       id = g_dbus_method_invocation_get_sender(invocation);
+       if (strcmp(spi_handle->client_info.id, id)) {
+               _E("Invalid access, handle id : %s, current id : %s", spi_handle->client_info.id, id);
+               rx_data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+               ret = PERIPHERAL_ERROR_INVALID_OPERATION;
+               goto out;
+       }
+
+       ret = peripheral_bus_spi_read_write(spi_handle, tx_data_array, &rx_data_array, length);
+
+out:
+       peripheral_io_gdbus_spi_complete_read_write(spi, invocation, rx_data_array, ret);
+
+       return true;
+}
+
 void peripheral_bus_emit_gpio_changed(PeripheralIoGdbusGpio *gpio,
                                                                        gint pin,
                                                                        gint state)
@@ -1191,6 +1629,85 @@ static gboolean __uart_init(peripheral_bus_s *pb_data)
        return true;
 }
 
+static gboolean __spi_init(peripheral_bus_s *pb_data)
+{
+       GDBusObjectManagerServer *manager;
+       gboolean ret = FALSE;
+       GError *error = NULL;
+
+       /* Add interface to default object path */
+       pb_data->spi_skeleton = peripheral_io_gdbus_spi_skeleton_new();
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-open",
+                       G_CALLBACK(handle_spi_open),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-close",
+                       G_CALLBACK(handle_spi_close),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-set-mode",
+                       G_CALLBACK(handle_spi_set_mode),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-get-mode",
+                       G_CALLBACK(handle_spi_get_mode),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-set-lsb-first",
+                       G_CALLBACK(handle_spi_set_lsb_first),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-get-lsb-first",
+                       G_CALLBACK(handle_spi_get_lsb_first),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-set-bits",
+                       G_CALLBACK(handle_spi_set_bits),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-get-bits",
+                       G_CALLBACK(handle_spi_get_bits),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-set-frequency",
+                       G_CALLBACK(handle_spi_set_frequency),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-get-frequency",
+                       G_CALLBACK(handle_spi_get_frequency),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-write",
+                       G_CALLBACK(handle_spi_write),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-read",
+                       G_CALLBACK(handle_spi_read),
+                       pb_data);
+       g_signal_connect(pb_data->spi_skeleton,
+                       "handle-read-write",
+                       G_CALLBACK(handle_spi_read_write),
+                       pb_data);
+
+       manager = g_dbus_object_manager_server_new(PERIPHERAL_GDBUS_SPI_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->spi_skeleton),
+               pb_data->connection, PERIPHERAL_GDBUS_SPI_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)
@@ -1209,6 +1726,9 @@ static void on_bus_acquired(GDBusConnection *connection,
 
        if (__uart_init(pb_data) == FALSE)
                _E("Can not signal connect");
+
+       if (__spi_init(pb_data) == FALSE)
+               _E("Can not signal connect");
 }
 
 static void on_name_acquired(GDBusConnection *conn,
index 41e38b8..89bbeda 100644 (file)
@@ -28,6 +28,7 @@ typedef struct {
        GList *i2c_list;
        GList *pwm_list;
        GList *uart_list;
+       GList *spi_list;
        /* gdbus variable */
        guint reg_id;
        GDBusConnection *connection;
@@ -35,6 +36,7 @@ typedef struct {
        PeripheralIoGdbusI2c *i2c_skeleton;
        PeripheralIoGdbusPwm *pwm_skeleton;
        PeripheralIoGdbusUart *uart_skeleton;
+       PeripheralIoGdbusSpi *spi_skeleton;
 } peripheral_bus_s;
 
 typedef struct {
@@ -95,10 +97,26 @@ typedef struct {
        pb_client_info_s client_info;
 } peripheral_bus_uart_data_s;
 
+typedef struct {
+       int bus;
+       int cs;
+       int fd;
+       /* data buffer */
+       uint8_t *rx_buf;
+       uint8_t *tx_buf;
+       int rx_buf_size;
+       int tx_buf_size;
+       uint watch_id;
+       GList **list;
+       /* client info */
+       pb_client_info_s client_info;
+} peripheral_bus_spi_data_s;
+
 typedef peripheral_bus_gpio_data_s *pb_gpio_data_h;
 typedef peripheral_bus_i2c_data_s *pb_i2c_data_h;
 typedef peripheral_bus_pwm_data_s *pb_pwm_data_h;
 typedef peripheral_bus_uart_data_s *pb_uart_data_h;
+typedef peripheral_bus_spi_data_s *pb_spi_data_h;
 
 void peripheral_bus_emit_gpio_changed(PeripheralIoGdbusGpio *gpio,
                                                                        gint pin,
diff --git a/src/daemon/peripheral_bus_spi.c b/src/daemon/peripheral_bus_spi.c
new file mode 100644 (file)
index 0000000..9047ead
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 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 "spi.h"
+#include "peripheral_bus.h"
+#include "peripheral_common.h"
+#include "peripheral_bus_util.h"
+
+static int initial_buffer_size = 128;
+static int max_buffer_size = 4096;
+
+static pb_spi_data_h peripheral_bus_spi_data_get(int bus, int cs, GList **list)
+{
+       GList *spi_list = *list;
+       GList *link;
+       pb_spi_data_h spi_handle;
+
+       link = spi_list;
+       while (link) {
+               spi_handle = (pb_spi_data_h)link->data;
+               if (spi_handle->bus == bus && spi_handle->cs == cs)
+                       return spi_handle;
+               link = g_list_next(link);
+       }
+
+       return NULL;
+}
+
+static pb_spi_data_h peripheral_bus_spi_data_new(GList **list)
+{
+       GList *spi_list = *list;
+       pb_spi_data_h spi_handle;
+
+       spi_handle = (pb_spi_data_h)calloc(1, sizeof(peripheral_bus_spi_data_s));
+       if (spi_handle == NULL) {
+               _E("failed to allocate peripheral_bus_spi_data_s");
+               return NULL;
+       }
+
+       *list = g_list_append(spi_list, spi_handle);
+
+       return spi_handle;
+}
+
+static int peripheral_bus_spi_data_free(pb_spi_data_h spi_handle, GList **spi_list)
+{
+       GList *link;
+
+       RETVM_IF(spi_handle == NULL, -1, "handle is null");
+
+       link = g_list_find(*spi_list, spi_handle);
+       if (!link) {
+               _E("handle does not exist in list");
+               return -1;
+       }
+
+       *spi_list = g_list_remove_link(*spi_list, link);
+       if (spi_handle->rx_buf)
+               free(spi_handle->rx_buf);
+       if (spi_handle->tx_buf)
+               free(spi_handle->tx_buf);
+       free(spi_handle);
+       g_list_free(link);
+
+       return 0;
+}
+
+int peripheral_bus_spi_open(int bus, int cs, pb_spi_data_h *spi, gpointer user_data)
+{
+       peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
+       pb_spi_data_h spi_handle;
+       int ret = PERIPHERAL_ERROR_NONE;
+       int fd, bufsiz;
+
+       if (peripheral_bus_spi_data_get(bus, cs, &pb_data->spi_list)) {
+               _E("Resource is in use, bus : %d, cs : %d", bus, cs);
+               return PERIPHERAL_ERROR_RESOURCE_BUSY;
+       }
+
+       if ((ret = spi_open(bus, cs, &fd)) < 0)
+               goto err_open;
+
+       spi_handle = peripheral_bus_spi_data_new(&pb_data->spi_list);
+       if (!spi_handle) {
+               _E("peripheral_bus_spi_data_new error");
+               ret = PERIPHERAL_ERROR_OUT_OF_MEMORY;
+               goto err_spi_data;
+       }
+
+       spi_handle->fd = fd;
+       spi_handle->bus = bus;
+       spi_handle->cs = cs;
+       spi_handle->list = &pb_data->spi_list;
+
+       if (!spi_get_buffer_size(&bufsiz)) {
+               if (initial_buffer_size > bufsiz) initial_buffer_size = bufsiz;
+               if (max_buffer_size > bufsiz) max_buffer_size = bufsiz;
+       }
+
+       spi_handle->rx_buf = (uint8_t*)calloc(1, initial_buffer_size);
+       if (!spi_handle->rx_buf) {
+               _E("Failed to allocate rx buffer");
+               ret =  PERIPHERAL_ERROR_OUT_OF_MEMORY;
+               goto err_rx_buf;
+       }
+       spi_handle->tx_buf = (uint8_t*)calloc(1, initial_buffer_size);
+       if (!spi_handle->rx_buf) {
+               _E("Failed to allocate tx buffer");
+               ret =  PERIPHERAL_ERROR_OUT_OF_MEMORY;
+               goto err_tx_buf;
+       }
+
+       spi_handle->rx_buf_size = initial_buffer_size;
+       spi_handle->tx_buf_size = initial_buffer_size;
+       *spi = spi_handle;
+
+       return PERIPHERAL_ERROR_NONE;
+
+err_tx_buf:
+       if (spi_handle->rx_buf)
+               free(spi_handle->rx_buf);
+       spi_handle->rx_buf_size = 0;
+
+err_rx_buf:
+       peripheral_bus_spi_data_free(spi_handle, &pb_data->spi_list);
+
+err_spi_data:
+       spi_close(fd);
+
+err_open:
+       return ret;
+}
+
+int peripheral_bus_spi_close(pb_spi_data_h spi)
+{
+       int ret;
+
+       if ((ret = spi_close(spi->fd)) < 0) {
+               _E("spi_close error (%d)", ret);
+               return ret;
+       }
+
+       if (peripheral_bus_spi_data_free(spi, spi->list) < 0) {
+               _E("Failed to free spi data");
+               return PERIPHERAL_ERROR_UNKNOWN;
+       }
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
+int peripheral_bus_spi_set_mode(pb_spi_data_h spi, unsigned char mode)
+{
+       return spi_set_mode(spi->fd, mode);
+}
+
+int peripheral_bus_spi_get_mode(pb_spi_data_h spi, unsigned char *mode)
+{
+       return spi_get_mode(spi->fd, mode);
+}
+
+int peripheral_bus_spi_set_lsb_first(pb_spi_data_h spi, gboolean lsb)
+{
+       return spi_set_lsb_first(spi->fd, (unsigned char)lsb);
+}
+
+int peripheral_bus_spi_get_lsb_first(pb_spi_data_h spi, gboolean *lsb)
+{
+       int ret;
+       unsigned char value;
+
+       if ((ret = spi_get_lsb_first(spi->fd, &value)) < 0) {
+               _E("spi_get_lsb_first error (%d)", ret);
+               return ret;
+       }
+       *lsb = value ? true : false;
+
+       return PERIPHERAL_ERROR_NONE;
+}
+
+int peripheral_bus_spi_set_bits(pb_spi_data_h spi, unsigned char bits)
+{
+       return spi_set_bits(spi->fd, bits);
+}
+
+int peripheral_bus_spi_get_bits(pb_spi_data_h spi, unsigned char *bits)
+{
+       return spi_get_bits(spi->fd, bits);
+}
+
+int peripheral_bus_spi_set_frequency(pb_spi_data_h spi, unsigned int freq)
+{
+       return spi_set_frequency(spi->fd, freq);
+}
+
+int peripheral_bus_spi_get_frequency(pb_spi_data_h spi, unsigned int *freq)
+{
+       return spi_get_frequency(spi->fd, freq);
+}
+
+int peripheral_bus_spi_read(pb_spi_data_h spi, GVariant **data_array, int length)
+{
+       uint8_t err_buf[2] = {0, };
+       int ret;
+
+       /* Limit maximum length */
+       if (length > max_buffer_size) length = max_buffer_size;
+
+       /* Increase buffer if needed */
+       if (length > spi->rx_buf_size) {
+               uint8_t *buffer;
+
+               buffer = (uint8_t*)realloc(spi->rx_buf, length);
+               if (!buffer) {
+                       ret = PERIPHERAL_ERROR_OUT_OF_MEMORY;
+                       _E("Failed to realloc buffer");
+                       goto out;
+               }
+               spi->rx_buf = buffer;
+               spi->rx_buf_size = length;
+       }
+
+       ret = spi_read(spi->fd, spi->rx_buf, length);
+       *data_array = peripheral_bus_build_variant_ay(spi->rx_buf, length);
+
+       return ret;
+
+out:
+       *data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+
+       return ret;
+}
+
+int peripheral_bus_spi_write(pb_spi_data_h spi, 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 > spi->tx_buf_size) {
+               uint8_t *buffer;
+
+               buffer = (uint8_t*)realloc(spi->tx_buf, length);
+               RETVM_IF(buffer == NULL, PERIPHERAL_ERROR_OUT_OF_MEMORY, "Failed to realloc tx buffer");
+
+               spi->tx_buf = buffer;
+               spi->tx_buf_size = length;
+       }
+
+       g_variant_get(data_array, "a(y)", &iter);
+       while (g_variant_iter_loop(iter, "(y)", &str) && i < length)
+               spi->tx_buf[i++] = str;
+       g_variant_iter_free(iter);
+
+       return spi_write(spi->fd, spi->tx_buf, length);
+}
+
+int peripheral_bus_spi_read_write(pb_spi_data_h spi, GVariant *tx_data_array, GVariant **rx_data_array, int length)
+{
+       uint8_t err_buf[2] = {0, };
+       GVariantIter *iter;
+       guchar str;
+       int i = 0;
+       int ret;
+
+       /* Limit maximum length */
+       if (length > max_buffer_size) length = max_buffer_size;
+
+       /* Increase rx buffer if needed */
+       if (length > spi->rx_buf_size) {
+               uint8_t *buffer;
+
+               buffer = (uint8_t*)realloc(spi->rx_buf, length);
+               if (!buffer) {
+                       ret = PERIPHERAL_ERROR_OUT_OF_MEMORY;
+                       _E("Failed to realloc rx buffer");
+                       goto out;
+               }
+               spi->rx_buf = buffer;
+               spi->rx_buf_size = length;
+       }
+
+       /* Increase tx buffer if needed */
+       if (length > spi->tx_buf_size) {
+               uint8_t *buffer;
+
+               buffer = (uint8_t*)realloc(spi->tx_buf, length);
+               if (!buffer) {
+                       ret = PERIPHERAL_ERROR_OUT_OF_MEMORY;
+                       _E("Failed to realloc tx buffer");
+                       goto out;
+               }
+
+               spi->tx_buf = buffer;
+               spi->tx_buf_size = length;
+       }
+       g_variant_get(tx_data_array, "a(y)", &iter);
+       while (g_variant_iter_loop(iter, "(y)", &str) && i < length)
+               spi->tx_buf[i++] = str;
+       g_variant_iter_free(iter);
+
+       ret = spi_read_write(spi->fd, spi->tx_buf, spi->rx_buf, length);
+       *rx_data_array = peripheral_bus_build_variant_ay(spi->rx_buf, length);
+
+       return ret;
+
+out:
+       *rx_data_array = peripheral_bus_build_variant_ay(err_buf, sizeof(err_buf));
+
+       return ret;
+}
diff --git a/src/daemon/peripheral_bus_spi.h b/src/daemon/peripheral_bus_spi.h
new file mode 100644 (file)
index 0000000..e1c3999
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#ifndef __PERIPHERAL_BUS_SPI_H__
+#define __PERIPHERAL_BUS_SPI_H__
+
+int peripheral_bus_spi_open(int bus, int cs, pb_spi_data_h *spi, gpointer user_data);
+int peripheral_bus_spi_close(pb_spi_data_h spi);
+int peripheral_bus_spi_set_mode(pb_spi_data_h spi, unsigned char mode);
+int peripheral_bus_spi_get_mode(pb_spi_data_h spi, unsigned char *mode);
+int peripheral_bus_spi_set_lsb_first(pb_spi_data_h spi, gboolean lsb);
+int peripheral_bus_spi_get_lsb_first(pb_spi_data_h spi, gboolean *lsb);
+int peripheral_bus_spi_set_bits(pb_spi_data_h spi, unsigned char bits);
+int peripheral_bus_spi_get_bits(pb_spi_data_h spi, unsigned char *bits);
+int peripheral_bus_spi_set_frequency(pb_spi_data_h spi, unsigned int freq);
+int peripheral_bus_spi_get_frequency(pb_spi_data_h spi, unsigned int *freq);
+int peripheral_bus_spi_read(pb_spi_data_h spi, GVariant **data_array, int length);
+int peripheral_bus_spi_write(pb_spi_data_h spi, GVariant *data_array, int length);
+int peripheral_bus_spi_read_write(pb_spi_data_h spi, GVariant *tx_data_array, GVariant **rx_data_array, int length);
+
+#endif /* __PERIPHERAL_BUS_SPI_H__ */
index 2480f92..c6fff55 100644 (file)
                        <arg type="i" name="result" direction="out"/>
                </method>
        </interface>
+       <interface name="org.tizen.peripheral_io.spi">
+               <method name="Open">
+                       <arg type="i" name="bus" direction="in"/>
+                       <arg type="i" name="cs" 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"/>
+               </method>
+               <method name="SetMode">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="y" name="mode" direction="in"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="GetMode">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="y" name="mode" direction="out"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="SetLsbFirst">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="b" name="lsb" direction="in"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="GetLsbFirst">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="b" name="lsb" direction="out"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="SetBits">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="y" name="bits" direction="in"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="GetBits">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="y" name="bits" direction="out"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="SetFrequency">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="u" name="freq" direction="in"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="GetFrequency">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="u" name="freq" direction="out"/>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="Read">
+                       <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"/>
+                       </arg>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="Write">
+                       <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"/>
+                       </arg>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+               <method name="ReadWrite">
+                       <arg type="u" name="handle" direction="in"/>
+                       <arg type="i" name="length" direction="in"/>
+                       <arg type="a(y)" name="tx_data" direction="in">
+                               <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>
+                       </arg>
+                       <arg type="a(y)" name="rx_data" direction="out">
+                               <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>
+                       </arg>
+                       <arg type="i" name="result" direction="out"/>
+               </method>
+       </interface>
 </node>
index 0ff0c44..ee637a0 100644 (file)
 #ifndef __SPI_H__
 #define __SPI_H__
 
-#define SYSFS_SPI_DIR "/dev/spidev"
-#define SPI_BUFFER_MAX 64
-#define SPI_CR1_LSBFIRST          (1 << 7)  /* Bit 7: Frame Format */
-
-typedef enum {
-       SPI_MODE0 = 0,
-       SPI_MODE1,
-       SPI_MODE2,
-       SPI_MODE3
-} spi_mode_e;
-
-int spi_open(unsigned int bus, int *file_hndl);
-int spi_close(int file_hndl);
-int spi_set_mode(int file_hndl, spi_mode_e mode);
-int spi_set_bits(int file_hndl, int bits);
-int spi_set_frequency(int file_hndl, int freq);
-int spi_set_chip_select(int file_hndl, int cs);
-int spi_get_mode(int file_hndl, spi_mode_e *mode);
-int spi_get_bits(int file_hndl, int *bits);
-int spi_get_frequency(int file_hndl, int *freq);
-int spi_get_lsb(int file_hndl, int *lsb);
-
-int spi_write_data(int file_hndl, char *txbuf, int length);
-int spi_read_data(int file_hndl, char *rxbuf, int length);
-int spi_exchange_data(int file_hndl, char *txbuf, char *rxbuf, int length);
+int spi_open(int bus, int cs, int *fd);
+int spi_close(int fd);
+int spi_set_mode(int fd, unsigned char mode);
+int spi_get_mode(int fd, unsigned char *mode);
+int spi_set_lsb_first(int fd, unsigned char lsb);
+int spi_get_lsb_first(int fd, unsigned char *lsb);
+int spi_set_bits(int fd, unsigned char bits);
+int spi_get_bits(int fd, unsigned char *bits);
+int spi_set_frequency(int fd, unsigned int freq);
+int spi_get_frequency(int fd, unsigned int *freq);
+int spi_get_buffer_size(int *bufsiz);
+int spi_read(int fd, unsigned char *rxbuf, int length);
+int spi_write(int fd, unsigned char *txbuf, int length);
+int spi_read_write(int fd, unsigned char *txbuf, unsigned char *rxbuf, int length);
 
 #endif /* __SPI_H__ */
index 49da2e6..6cd6909 100644 (file)
 #include "spi.h"
 #include "peripheral_common.h"
 
-int spi_open(unsigned int bus, int *file_hndl)
+#define SYSFS_SPI_DIR "/dev/spidev"
+#define SYSFS_SPI_BUFSIZ "/sys/module/spidev/parameters/bufsiz"
+#define SPI_BUFFER_MAX 64
+#define MAX_ERR_LEN 255
+
+int spi_open(int bus, int cs, int *fd)
 {
-       int fd = 0;
+       int new_fd = 0;
        char spi_dev[SPI_BUFFER_MAX] = {0,};
 
-       snprintf(spi_dev, sizeof(spi_dev)-1, SYSFS_SPI_DIR"%d", bus);
+       snprintf(spi_dev, sizeof(spi_dev)-1, SYSFS_SPI_DIR"%d.%d", bus, cs);
 
-       fd = open(spi_dev, O_RDWR);
-       if (file_hndl < 0) {
-               _E("Can't Open /dev/spidev%d.0 :%s\n", bus, strerror(errno));
-               return -ENOENT;
+       new_fd = open(spi_dev, O_RDWR);
+       if (new_fd < 0) {
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Can't Open %s, errmsg : %s", spi_dev, errmsg);
+               return -ENODEV;
        }
-
-       *file_hndl = fd;
+       *fd = new_fd;
 
        return 0;
 }
 
-int spi_close(int file_hndl)
+int spi_close(int fd)
 {
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       int status;
+
+       if (fd < 0) return -EINVAL;
 
-       close(file_hndl);
+       status = close(fd);
+       if (status < 0) {
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to close fd : %d", fd);
+               return -EIO;
+       }
 
        return 0;
 }
 
-int spi_set_mode(int file_hndl, spi_mode_e mode)
+int spi_set_mode(int fd, unsigned char mode)
 {
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       status = ioctl(file_hndl, SPI_IOC_WR_MODE, &mode);
+       _D("Set mode : %d", mode);
+       status = ioctl(fd, SPI_IOC_WR_MODE, &mode);
        if (status < 0) {
-               _E("Error: spi_set_mode %d fail\n", mode);
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to set mode(%d) : %s", mode, errmsg);
+               return -EIO;
        }
 
        return 0;
 }
 
-int spi_set_bits(int file_hndl, int bits)
+int spi_get_mode(int fd, unsigned char *mode)
 {
+       unsigned char value = 0;
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
-
-       status = ioctl(file_hndl, SPI_IOC_WR_BITS_PER_WORD, &bits);
+       if (fd < 0) return -EINVAL;
 
+       status = ioctl(fd, SPI_IOC_RD_MODE, &value);
        if (status < 0) {
-               _E("Error: spi_set_bits %d fail\n", bits);
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to get mode : %s", errmsg);
+               return -EIO;
        }
+       *mode = value;
 
        return 0;
 }
 
-int spi_set_frequency(int file_hndl, int freq)
+int spi_set_lsb_first(int fd, unsigned char lsb)
 {
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
-
-       status = ioctl(file_hndl, SPI_IOC_WR_MAX_SPEED_HZ, &freq);
+       if (fd < 0) return -EINVAL;
 
+       _D("Set lsb first : %d", lsb);
+       status = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb);
        if (status < 0) {
-               _E("Error: spi_set_frequency %d fail\n", freq);
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to set lsb first(%d) : %s", lsb, errmsg);
+               return -EIO;
        }
 
        return 0;
 }
 
-int spi_set_chip_select(int file_hndl, int cs)
+int spi_get_lsb_first(int fd, unsigned char *lsb)
 {
-       int mode = 0;
+       unsigned char value = 0;
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       status = ioctl(file_hndl, SPI_IOC_RD_MODE, &mode);
+       status = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &value);
        if (status < 0) {
-               _E("Error: Get: spi_set_chip_select fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to get lsb first : %s", errmsg);
+               return -EIO;
        }
+       *lsb = value ? 1 : 0;
+
+       return 0;
+}
 
-       if (cs == 1)
-               mode |= SPI_CS_HIGH;
-       else
-               mode &= SPI_CS_HIGH;
+int spi_set_bits(int fd, unsigned char bits)
+{
+       int status;
 
-       _D("mode[%x]\n", mode);
+       if (fd < 0) return -EINVAL;
 
-       status = ioctl(file_hndl, SPI_IOC_WR_MODE, &mode);
+       _D("Set bit per word : %d", bits);
+       status = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
        if (status < 0) {
-               _E("Error: Set : spi_set_chip_select %d fail\n", mode);
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to set bits(%d) : %s", bits, errmsg);
+               return -EIO;
        }
 
        return 0;
 }
 
-int spi_get_mode(int file_hndl, spi_mode_e *mode)
+int spi_get_bits(int fd, unsigned char *bits)
 {
-       int value = 0;
+       unsigned char value = 0;
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       status = ioctl(file_hndl, SPI_IOC_RD_MODE, &value);
+       status = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &value);
        if (status < 0) {
-               _E("Error: spi_get_mode fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to get bits : %s", errmsg);
+               return -EIO;
        }
-
-       *mode = value;
+       *bits = value;
 
        return 0;
 }
 
-int spi_get_bits(int file_hndl, int *bits)
+int spi_set_frequency(int fd, unsigned int freq)
 {
-       int value = 0;
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       status = ioctl(file_hndl, SPI_IOC_RD_BITS_PER_WORD, &value);
+       _D("Set frequency : %d", freq);
+       status = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &freq);
        if (status < 0) {
-               _E("Error: spi_get_bits fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to set frequency(%d) : %s", freq, errmsg);
+               return -EIO;
        }
 
-       *bits = value;
-
        return 0;
 }
 
-int spi_get_frequency(int file_hndl, int *freq)
+int spi_get_frequency(int fd, unsigned int *freq)
 {
-       int value = 0;
+       unsigned int value = 0;
        int status;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
-
-       status = ioctl(file_hndl, SPI_IOC_RD_MAX_SPEED_HZ, &value);
+       if (fd < 0) return -EINVAL;
 
+       status = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &value);
        if (status < 0) {
-               _E("Error: spi_get_frequency fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to get frequency : %s", errmsg);
+               return -EIO;
        }
-
        *freq = value;
 
        return 0;
 }
 
-int spi_get_lsb(int file_hndl, int *lsb)
+int spi_get_buffer_size(int *bufsiz)
 {
-       int value = 0;
-       int status;
-
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
-
-       status = ioctl(file_hndl, SPI_IOC_RD_LSB_FIRST, &value);
+       int fd, result, status;
+       char spi_buf[SPI_BUFFER_MAX] = {0,};
+
+       fd = open(SYSFS_SPI_BUFSIZ, O_RDONLY);
+       if (fd < 0) {
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Can't Open %s, errmsg : %s", SYSFS_SPI_BUFSIZ, errmsg);
+               return -ENODEV;
+       }
 
+       status = read(fd, spi_buf, SPI_BUFFER_MAX);
        if (status < 0) {
-               _E("Error: spi_get_lsb fail\n");
-               return -1;
+               _E("Failed to get buffer size, path : %s", SYSFS_SPI_BUFSIZ);
+               close(fd);
+               return -EIO;
        }
-
-       *lsb = value;
+       result = atoi(spi_buf);
+       *bufsiz = result;
+       close(fd);
 
        return 0;
 }
 
-int spi_write_data(int file_hndl, char *txbuf, int length)
+int spi_read(int fd, unsigned char *rxbuf, int length)
 {
        int status;
        struct spi_ioc_transfer xfer;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       memset(&xfer, 0, sizeof(xfer));
-       xfer.tx_buf = (unsigned long)txbuf;
+       memset(&xfer, 0, sizeof(struct spi_ioc_transfer));
+       xfer.rx_buf = (unsigned long)rxbuf;
        xfer.len = length;
 
-       status = ioctl(file_hndl, SPI_IOC_MESSAGE(1), xfer);
+       status = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer);
        if (status < 0) {
-               _E("Error: spi_write_data fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to read data(%d) : %s", length, errmsg);
+               return -EIO;
        }
 
        return 0;
 }
 
-int spi_read_data(int file_hndl, char *rxbuf, int length)
+int spi_write(int fd, unsigned char *txbuf, int length)
 {
        int status;
        struct spi_ioc_transfer xfer;
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       memset(&xfer, 0, sizeof(xfer));
-       xfer.rx_buf = (unsigned long)rxbuf;
+       memset(&xfer, 0, sizeof(struct spi_ioc_transfer));
+       xfer.tx_buf = (unsigned long)txbuf;
        xfer.len = length;
 
-       status = ioctl(file_hndl, SPI_IOC_MESSAGE(1), &xfer);
+       status = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer);
        if (status < 0) {
-               _E("Error: spi_read_data fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to write data(%d) : %s", length, errmsg);
+               return -EIO;
        }
+
        return 0;
 }
 
-int spi_exchange_data(int file_hndl, char *txbuf, char *rxbuf, int length)
+int spi_read_write(int fd, unsigned char *txbuf, unsigned char *rxbuf, int length)
 {
        int status;
        struct spi_ioc_transfer xfer[2];
 
-       if (file_hndl == (int)NULL)
-               return -EINVAL;
+       if (fd < 0) return -EINVAL;
 
-       if (!txbuf || length < 0)
-               return -EINVAL;
+       if (!txbuf || !rxbuf || length < 0) return -EINVAL;
 
        memset(xfer, 0, sizeof(xfer));
        xfer[0].tx_buf = (unsigned long)txbuf;
        xfer[0].len = length;
-
        xfer[1].rx_buf = (unsigned long)rxbuf;
        xfer[1].len = length;
 
-       status = ioctl(file_hndl, SPI_IOC_MESSAGE(2), xfer);
+       status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
        if (status < 0) {
-               _E("Error: spi_exchange_data fail\n");
-               return -1;
+               char errmsg[MAX_ERR_LEN];
+               strerror_r(errno, errmsg, MAX_ERR_LEN);
+               _E("Failed to exchange data(%d) : %s", length, errmsg);
+               return -EIO;
        }
 
        return 0;