From f2e8133bf840f9e26822d563a4b0d48d7af1b326 Mon Sep 17 00:00:00 2001 From: "jino.cho" Date: Thu, 25 May 2017 19:50:58 +0900 Subject: [PATCH] Add APIs and functions for the spi device This patch support the spi device. And, it should work properly if the patch for peripheral-bus is applied together. Change-Id: Ia0094e516d5dff9fba1e2d40170dc7cce844d347 Signed-off-by: jino.cho --- CMakeLists.txt | 2 + include/peripheral_gdbus.h | 1 + include/peripheral_gdbus_spi.h | 36 ++++ include/peripheral_internal.h | 7 + include/peripheral_io.h | 234 ++++++++++++++++++++++-- src/peripheral_gdbus_spi.c | 406 +++++++++++++++++++++++++++++++++++++++++ src/peripheral_io.xml | 79 ++++++++ src/peripheral_spi.c | 121 +++++++++++- test/peripheral-io-test.c | 79 +++++++- 9 files changed, 935 insertions(+), 30 deletions(-) create mode 100644 include/peripheral_gdbus_spi.h create mode 100644 src/peripheral_gdbus_spi.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d051617..ebacf9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,10 +47,12 @@ SET(SOURCES src/peripheral_gpio.c src/peripheral_pwm.c src/peripheral_adc.c src/peripheral_uart.c + src/peripheral_spi.c src/peripheral_gdbus_gpio.c src/peripheral_gdbus_i2c.c src/peripheral_gdbus_pwm.c src/peripheral_gdbus_uart.c + src/peripheral_gdbus_spi.c src/peripheral_io_gdbus.c src/peripheral_spi.c) diff --git a/include/peripheral_gdbus.h b/include/peripheral_gdbus.h index aefe770..ff726de 100644 --- a/include/peripheral_gdbus.h +++ b/include/peripheral_gdbus.h @@ -23,6 +23,7 @@ #define PERIPHERAL_GDBUS_I2C_PATH "/Org/Tizen/Peripheral_io/I2c" #define PERIPHERAL_GDBUS_PWM_PATH "/Org/Tizen/Peripheral_io/Pwm" #define PERIPHERAL_GDBUS_UART_PATH "/Org/Tizen/Peripheral_io/Uart" +#define PERIPHERAL_GDBUS_SPI_PATH "/Org/Tizen/Peripheral_io/Spi" #define PERIPHERAL_GDBUS_NAME "org.tizen.peripheral_io" #endif /* __PERIPHERAL_GDBUS_H__ */ diff --git a/include/peripheral_gdbus_spi.h b/include/peripheral_gdbus_spi.h new file mode 100644 index 0000000..78e7e97 --- /dev/null +++ b/include/peripheral_gdbus_spi.h @@ -0,0 +1,36 @@ +/* + * 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. + */ +#ifndef __PERIPHERAL_GDBUS_SPI_H_ +#define __PERIPHERAL_GDBUS_SPI_H_ + +void spi_proxy_init(void); +void spi_proxy_deinit(); + +int peripheral_gdbus_spi_open(peripheral_spi_h spi, int bus, int cs); +int peripheral_gdbus_spi_close(peripheral_spi_h spi); +int peripheral_gdbus_spi_set_mode(peripheral_spi_h spi, peripheral_spi_mode_e mode); +int peripheral_gdbus_spi_get_mode(peripheral_spi_h spi, peripheral_spi_mode_e *mode); +int peripheral_gdbus_spi_set_lsb_first(peripheral_spi_h spi, bool lsb); +int peripheral_gdbus_spi_get_lsb_first(peripheral_spi_h spi, bool *lsb); +int peripheral_gdbus_spi_set_bits(peripheral_spi_h spi, unsigned char bits); +int peripheral_gdbus_spi_get_bits(peripheral_spi_h spi, unsigned char *bits); +int peripheral_gdbus_spi_set_frequency(peripheral_spi_h spi, unsigned int freq); +int peripheral_gdbus_spi_get_frequency(peripheral_spi_h spi, unsigned int *freq); +int peripheral_gdbus_spi_read(peripheral_spi_h spi, unsigned char *data, int length); +int peripheral_gdbus_spi_write(peripheral_spi_h spi, unsigned char *data, int length); +int peripheral_gdbus_spi_read_write(peripheral_spi_h spi, unsigned char *tx_data, unsigned char *rx_data, int length); + +#endif /* __PERIPHERAL_GDBUS_SPI_H_ */ diff --git a/include/peripheral_internal.h b/include/peripheral_internal.h index 34f09b0..ae4f47e 100644 --- a/include/peripheral_internal.h +++ b/include/peripheral_internal.h @@ -46,4 +46,11 @@ struct _peripheral_uart_s { uint handle; }; +/** + * @brief Internal struct for spi context + */ +struct _peripheral_spi_s { + uint handle; +}; + #endif /* __PERIPHERAL_INTERNAL_H__ */ diff --git a/include/peripheral_io.h b/include/peripheral_io.h index 7517d2a..8e126c8 100644 --- a/include/peripheral_io.h +++ b/include/peripheral_io.h @@ -825,33 +825,231 @@ int peripheral_uart_write(peripheral_uart_h uart, uint8_t *data, int length); * @{ */ +/** + * @brief The handle to the spi device + * @since_tizen 4.0 + */ +typedef struct _peripheral_spi_s* peripheral_spi_h; + +/** + * @brief Enumeration for SPI mode. + */ typedef enum { - PERIPHERAL_SPI_MODE0 = 0, - PERIPHERAL_SPI_MODE1, - PERIPHERAL_SPI_MODE2, - PERIPHERAL_SPI_MODE3 + PERIPHERAL_SPI_MODE_0 = 0, + PERIPHERAL_SPI_MODE_1, + PERIPHERAL_SPI_MODE_2, + PERIPHERAL_SPI_MODE_3 } peripheral_spi_mode_e; -struct peripheral_spi_config_s { - int fd; - char bits_per_word; - int lsb; - unsigned int chip_select; - unsigned int frequency; - peripheral_spi_mode_e mode; -}; +/** + * @brief Initializes spi communication and creates spi handle. + * @since_tizen 4.0 + * + * @param[in] bus The spi bus number that the slave device is connected + * @param[in] cs The spi chip select number that the slave device is connected + * @param[out] spi The spi handle is created on success + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * + * @see peripheral_spi_close() + */ +int peripheral_spi_open(int bus, int cs, peripheral_spi_h *spi); + +/** + * @brief Destory the spi handle and release the communication. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * + * @see peripheral_spi_open() + */ +int peripheral_spi_close(peripheral_spi_h spi); + +/** + * @brief Sets mode of the spi device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[in] mode The mode of the spi device + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_set_mode(peripheral_spi_h spi, peripheral_spi_mode_e mode); + +/** + * @brief Gets mode of the spi device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[out] mode The mode of the spi device + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_get_mode(peripheral_spi_h spi, peripheral_spi_mode_e *mode); + +/** + * @brief Sets bits justification of the spi device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[in] lsb The bit position to be transmitted first + * true - LSB first + * false - MSB first + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_set_lsb_first(peripheral_spi_h spi, bool lsb); + +/** + * @brief Gets bits justification of the spi device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[out] lsb The bit position to be transmitted first + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_get_lsb_first(peripheral_spi_h spi, bool *lsb); + +/** + * @brief Sets the number of bits per word of the spi device + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[in] bits The number of bits per word (in bits) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_set_bits_per_word(peripheral_spi_h spi, unsigned char bits); -typedef struct peripheral_spi_config_s * peripheral_spi_context_h; +/** + * @brief Gets the number of bits per word of the spi device + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[out] bits The number of bits per word (in bits) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_get_bits_per_word(peripheral_spi_h spi, unsigned char *bits); -peripheral_spi_context_h peripheral_spi_open(unsigned int bus, peripheral_spi_context_h config); +/** + * @brief Sets default max speed of the spi device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[in] freq Max speed (in hz) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ +int peripheral_spi_set_frequency(peripheral_spi_h spi, unsigned int freq); -int peripheral_spi_write(peripheral_spi_context_h hnd, char *txbuf, int length); +/** + * @brief Gets default max speed of the spi device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[out] freq Max speed (in hz) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + * @retval #PERIPHERAL_ERROR_NO_DEVICE Device is not exist or removed + */ -int peripheral_spi_recv(peripheral_spi_context_h hnd, char *rxbuf, int length); +int peripheral_spi_get_frequency(peripheral_spi_h spi, unsigned int *freq); -int peripheral_spi_transfer_buf(peripheral_spi_context_h hnd, char *txbuf, char *rxbuf, int length); +/** + * @brief Reads data from the slave device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[out] data The address of buffer to read + * @param[in] length The size of data buffer (in bytes) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + */ +int peripheral_spi_read(peripheral_spi_h spi, unsigned char *data, int length); + +/** + * @brief Write data to the slave device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[in] data The address of buffer to write + * @param[in] length The size of data (in bytes) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + */ +int peripheral_spi_write(peripheral_spi_h spi, unsigned char *data, int length); -int peripheral_spi_close(peripheral_spi_context_h hnd); +/** + * @brief Exchange data with the slave device. + * @since_tizen 4.0 + * + * @param[in] spi The handle to the spi device + * @param[in] txdata The address of buffer to write + * @param[out] rxdata The address of buffer to read + * @param[in] length The size of data (in bytes) + * + * @return 0 on success, otherwise a negative error value + * @retval #PERIPHERAL_ERROR_NONE Successful + * @retval #PERIPHERAL_ERROR_IO_ERROR I/O operation failed + * @retval #PERIPHERAL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #PERIPHERAL_ERROR_UNKNOWN Unknown internal error + */ +int peripheral_spi_read_write(peripheral_spi_h spi, unsigned char *txdata, unsigned char *rxdata, int length); /** * @} diff --git a/src/peripheral_gdbus_spi.c b/src/peripheral_gdbus_spi.c new file mode 100644 index 0000000..b42e926 --- /dev/null +++ b/src/peripheral_gdbus_spi.c @@ -0,0 +1,406 @@ +/* + * 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 +#include + +#include "peripheral_io.h" +#include "peripheral_gdbus.h" +#include "peripheral_common.h" +#include "peripheral_internal.h" +#include "peripheral_io_gdbus.h" + +PeripheralIoGdbusSpi *spi_proxy = NULL; + +void spi_proxy_init(void) +{ + GError *error = NULL; + + if (spi_proxy != NULL) { + g_object_ref(spi_proxy); + return; + } + + spi_proxy = peripheral_io_gdbus_spi_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + PERIPHERAL_GDBUS_NAME, + PERIPHERAL_GDBUS_SPI_PATH, + NULL, + &error); +} + +void spi_proxy_deinit() +{ + if (spi_proxy) { + g_object_unref(spi_proxy); + if (!G_IS_OBJECT(spi_proxy)) + spi_proxy = NULL; + } +} + +int peripheral_gdbus_spi_open(peripheral_spi_h spi, int bus, int cs) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_open_sync( + spi_proxy, + bus, + cs, + &spi->handle, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_close(peripheral_spi_h spi) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_close_sync( + spi_proxy, + spi->handle, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_set_mode(peripheral_spi_h spi, peripheral_spi_mode_e mode) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_set_mode_sync( + spi_proxy, + spi->handle, + (guchar)mode, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_get_mode(peripheral_spi_h spi, peripheral_spi_mode_e *mode) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + guchar value; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_get_mode_sync( + spi_proxy, + spi->handle, + &value, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + if (value <= PERIPHERAL_SPI_MODE_3) + *mode = value; + else + _E("Invalid mode : %d", value); + + return ret; +} + +int peripheral_gdbus_spi_set_lsb_first(peripheral_spi_h spi, bool lsb) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_set_lsb_first_sync( + spi_proxy, + spi->handle, + lsb, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_get_lsb_first(peripheral_spi_h spi, bool *lsb) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + gboolean value; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_get_lsb_first_sync( + spi_proxy, + spi->handle, + &value, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + *lsb = value ? true : false; + + return ret; +} + +int peripheral_gdbus_spi_set_bits(peripheral_spi_h spi, unsigned char bits) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_set_bits_sync( + spi_proxy, + spi->handle, + bits, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_get_bits(peripheral_spi_h spi, unsigned char *bits) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + guchar value; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_get_bits_sync( + spi_proxy, + spi->handle, + &value, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + *bits = (unsigned char)value; + + return ret; +} + +int peripheral_gdbus_spi_set_frequency(peripheral_spi_h spi, unsigned int freq) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_set_frequency_sync( + spi_proxy, + spi->handle, + freq, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_get_frequency(peripheral_spi_h spi, unsigned int *freq) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + guint value; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_get_frequency_sync( + spi_proxy, + spi->handle, + &value, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + *freq = (unsigned int)value; + + return ret; +} + +int peripheral_gdbus_spi_read(peripheral_spi_h spi, unsigned char *data, int length) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + GVariant *data_array; + GVariantIter *iter; + guint8 str; + int i = 0; + + if (spi_proxy == NULL || data == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + if (peripheral_io_gdbus_spi_call_read_sync( + spi_proxy, + spi->handle, + length, + &data_array, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + g_variant_get(data_array, "a(y)", &iter); + while (g_variant_iter_loop(iter, "(y)", &str)) { + data[i] = str; + if (i++ == length) break; + } + g_variant_iter_free(iter); + g_variant_unref(data_array); + + return ret; +} + +int peripheral_gdbus_spi_write(peripheral_spi_h spi, unsigned char *data, int length) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + GVariantBuilder *builder; + GVariant *data_array; + int i = 0; + + if (spi_proxy == NULL) return PERIPHERAL_ERROR_UNKNOWN; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)")); + + for (i = 0; i < length; i++) + g_variant_builder_add(builder, "(y)", data[i]); + g_variant_builder_add(builder, "(y)", 0x00); + + data_array = g_variant_new("a(y)", builder); + g_variant_builder_unref(builder); + + if (peripheral_io_gdbus_spi_call_write_sync( + spi_proxy, + spi->handle, + length, + data_array, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + return ret; +} + +int peripheral_gdbus_spi_read_write(peripheral_spi_h spi, unsigned char *tx_data, unsigned char *rx_data, int length) +{ + GError *error = NULL; + peripheral_error_e ret = PERIPHERAL_ERROR_NONE; + GVariantBuilder *builder; + GVariant *rx_data_array; + GVariant *tx_data_array; + GVariantIter *iter; + guint8 str; + int i = 0; + + if (spi_proxy == NULL || !rx_data || !tx_data) return PERIPHERAL_ERROR_UNKNOWN; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(y)")); + + for (i = 0; i < length; i++) + g_variant_builder_add(builder, "(y)", tx_data[i]); + g_variant_builder_add(builder, "(y)", 0x00); + + tx_data_array = g_variant_new("a(y)", builder); + g_variant_builder_unref(builder); + + if (peripheral_io_gdbus_spi_call_read_write_sync( + spi_proxy, + spi->handle, + length, + tx_data_array, + &rx_data_array, + &ret, + NULL, + &error) == FALSE) { + _E("%s", error->message); + g_error_free(error); + return PERIPHERAL_ERROR_UNKNOWN; + } + + i = 0; + g_variant_get(rx_data_array, "a(y)", &iter); + while (g_variant_iter_loop(iter, "(y)", &str)) { + rx_data[i] = str; + if (i++ == length) break; + } + g_variant_iter_free(iter); + g_variant_unref(rx_data_array); + + return ret; +} diff --git a/src/peripheral_io.xml b/src/peripheral_io.xml index 2480f92..c6fff55 100644 --- a/src/peripheral_io.xml +++ b/src/peripheral_io.xml @@ -182,4 +182,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/peripheral_spi.c b/src/peripheral_spi.c index e2f8465..661b68a 100644 --- a/src/peripheral_spi.c +++ b/src/peripheral_spi.c @@ -20,27 +20,128 @@ #include #include -peripheral_spi_context_h peripheral_spi_open(unsigned int bus, peripheral_spi_context_h config) +#include "peripheral_io.h" +#include "peripheral_gdbus_spi.h" +#include "peripheral_common.h" +#include "peripheral_internal.h" + +int peripheral_spi_open(int bus, int cs, peripheral_spi_h *spi) +{ + peripheral_spi_h handle; + int ret = PERIPHERAL_ERROR_NONE; + + if (bus < 0 || cs < 0) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + /* Initialize */ + handle = (peripheral_spi_h)calloc(1, sizeof(struct _peripheral_spi_s)); + + if (handle == NULL) { + _E("Failed to allocate peripheral_spi_h"); + return PERIPHERAL_ERROR_OUT_OF_MEMORY; + } + + spi_proxy_init(); + + ret = peripheral_gdbus_spi_open(handle, bus, cs); + + if (ret != PERIPHERAL_ERROR_NONE) { + _E("SPI open error (%d, %d)", bus, cs); + free(handle); + handle = NULL; + } + *spi = handle; + + return ret; +} + +int peripheral_spi_close(peripheral_spi_h spi) +{ + int ret = PERIPHERAL_ERROR_NONE; + + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + if ((ret = peripheral_gdbus_spi_close(spi)) < 0) + _E("Failed to close SPI device, continuing anyway"); + + spi_proxy_deinit(); + free(spi); + + return ret; +} + +int peripheral_spi_set_mode(peripheral_spi_h spi, peripheral_spi_mode_e mode) +{ + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_set_mode(spi, mode); +} + +int peripheral_spi_get_mode(peripheral_spi_h spi, peripheral_spi_mode_e *mode) +{ + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_get_mode(spi, mode); +} + +int peripheral_spi_set_lsb_first(peripheral_spi_h spi, bool lsb) +{ + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_set_lsb_first(spi, lsb); +} + +int peripheral_spi_get_lsb_first(peripheral_spi_h spi, bool *lsb) +{ + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_get_lsb_first(spi, lsb); +} + +int peripheral_spi_set_bits_per_word(peripheral_spi_h spi, unsigned char bits) +{ + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_set_bits(spi, bits); +} + +int peripheral_spi_get_bits_per_word(peripheral_spi_h spi, unsigned char *bits) +{ + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_get_bits(spi, bits); +} + +int peripheral_spi_set_frequency(peripheral_spi_h spi, unsigned int freq) { - return NULL; + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_set_frequency(spi, freq); } -int peripheral_spi_write(peripheral_spi_context_h hnd, char *txbuf, int length) +int peripheral_spi_get_frequency(peripheral_spi_h spi, unsigned int *freq) { - return PERIPHERAL_ERROR_INVALID_OPERATION; + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_get_frequency(spi, freq); } -int peripheral_spi_recv(peripheral_spi_context_h hnd, char *rxbuf, int length) +int peripheral_spi_read(peripheral_spi_h spi, unsigned char *data, int length) { - return PERIPHERAL_ERROR_INVALID_OPERATION; + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_read(spi, data, length); } -int peripheral_spi_transfer_buf(peripheral_spi_context_h hnd, char *txbuf, char *rxbuf, int length) +int peripheral_spi_write(peripheral_spi_h spi, unsigned char *data, int length) { - return PERIPHERAL_ERROR_INVALID_OPERATION; + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_write(spi, data, length); } -int peripheral_spi_close(peripheral_spi_context_h hnd) +int peripheral_spi_read_write(peripheral_spi_h spi, unsigned char *txdata, unsigned char *rxdata, int length) { - return PERIPHERAL_ERROR_INVALID_OPERATION; + if (spi == NULL) return PERIPHERAL_ERROR_INVALID_PARAMETER; + + return peripheral_gdbus_spi_read_write(spi, txdata, rxdata, length); } diff --git a/test/peripheral-io-test.c b/test/peripheral-io-test.c index 1ec14eb..d0aa4c6 100644 --- a/test/peripheral-io-test.c +++ b/test/peripheral-io-test.c @@ -519,6 +519,80 @@ err_open: return -1; } +#define MMA7455_MCTL_SPI3W 0x20 // SPI is 3 wire mode +#define MMA7455_MCTL_DRPD 0x40 // Data ready status is not output to INT1/DRDY PIN + +#define MMA7455_SPI_REGISTER_WRITE 0x40 + +int spi_mma7455_module_test(void) +{ + int cnt = 0; + int bus_num, cs_num, ret; + unsigned char tx_buf[10]; + unsigned char rx_buf[10]; + unsigned int num; + peripheral_spi_h spi; + + printf(" %s()\n", __func__); + printf("Enter SPI bus number : "); + if (scanf("%d", &bus_num) < 0) + return -1; + + printf("Enter SPI cs number : "); + if (scanf("%d", &cs_num) < 0) + return -1; + + if ((ret = peripheral_spi_open(bus_num, cs_num, &spi)) < 0) { + printf("Failed to open I2C communication, ret : %d\n", ret); + return -1; + } + peripheral_spi_set_mode(spi, PERIPHERAL_SPI_MODE_0); + peripheral_spi_set_lsb_first(spi, false); + peripheral_spi_set_bits_per_word(spi, 8); + peripheral_spi_set_frequency(spi, 100000); + + printf("bus : %d, cs : %d, ", bus_num, cs_num); + peripheral_spi_get_mode(spi, (peripheral_spi_mode_e*)&num); + printf("mode : %d, ", num); + peripheral_spi_get_lsb_first(spi, (bool*)&num); + printf("lsb first : %d, ", (bool)num); + peripheral_spi_get_bits_per_word(spi, (unsigned char*)&num); + printf("bits : %d, ", (unsigned char)num); + peripheral_spi_get_frequency(spi, &num); + printf("max frequency : %d\n", num); + + tx_buf[0] = (MMA7455_MCTL | MMA7455_SPI_REGISTER_WRITE) << 1; + tx_buf[1] = MMA7455_MCTL_DRPD | MMA7455_MCTL_SPI3W | MMA7455_MCTL_2G | MMA7455_MCTL_MEASUREMENT_MODE; + if ((ret = peripheral_spi_write(spi, tx_buf, 2)) < 0) { + printf("Failed to write, ret : %d\n", ret); + goto error; + } + + while (cnt++ < 15) { + int i; + unsigned char buf[5]; + + sleep(1); + for (i = 0; i < 3; i++) { + tx_buf[0] = (MMA7455_XOUT8 + i) << 1; + tx_buf[1] = 0; + ret = peripheral_spi_read_write(spi, tx_buf, rx_buf, 2); + if (ret < 0) + printf("Failed to read, ret : %d\n", ret); + buf[i] = rx_buf[1]; + } + + printf("X = 0x%02X, Y = 0x%02X, Z = 0x%02X\n", buf[0], buf[1], buf[2]); + } + + peripheral_spi_close(spi); + return 0; + +error: + peripheral_spi_close(spi); + return -1; +} + int gpio_test_get_handle_by_pin(int pin, peripheral_gpio_h *gpio) { peripheral_gpio_h handle; @@ -851,8 +925,9 @@ tc_table_t preset_tc_table[] = { {"[Preset Test] PWM LED", 4, pwm_test_led}, {"[Preset Test] PWM Motor", 5, pwm_test_motor}, {"[Preset Test] Uart Accelerometer", 6, uart_test_accelerometer}, - {"[Preset Test] GPIO IRQ register", 7, gpio_irq_register}, - {"[Preset Test] GPIO IRQ unregister", 8, gpio_irq_unregister}, + {"[Preset Test] SPI MMA7455 Accel. sensor", 7, spi_mma7455_module_test}, + {"[Preset Test] GPIO IRQ register", 8, gpio_irq_register}, + {"[Preset Test] GPIO IRQ unregister", 9, gpio_irq_unregister}, {"Go back to main", 0, enter_main}, {NULL, 0, NULL}, }; -- 2.7.4