SET(PREFIX ${CMAKE_INSTALL_PREFIX})
SET(VERSION 0.0.1)
-SET(dependents "dlog glib-2.0 gio-2.0 gio-unix-2.0")
+SET(dependents "dlog glib-2.0 gio-2.0 gio-unix-2.0 iniparser")
FIND_PROGRAM(GDBUS_CODEGEN NAMES gdbus-codegen)
EXEC_PROGRAM(${GDBUS_CODEGEN} ARGS
src/daemon/peripheral_bus_gpio.c
src/daemon/peripheral_bus_uart.c
src/daemon/peripheral_bus_spi.c
+ src/daemon/peripheral_bus_board.c
src/daemon/peripheral_io_gdbus.c
src/interface/adc.c
src/interface/gpio.c
--- /dev/null
+[gpio]
+gpio128 = 4
+gpio129 = 6
+gpio130 = 8
+gpio46 = 10
+gpio14 = 12
+gpio41 = 14
+gpio25 = 16
+gpio0 = 18
+gpio26 = 20
+gpio27 = 22
+
+[i2c]
+i2c-1 = 13, 15
+
+[pwm]
+pwmchip0/pwm2 = 30
+
+[adc]
+iio:device0/in_voltage_0_raw = 40
+iio:device0/in_voltage_1_raw = 1
+iio:device0/in_voltage_2_raw = 3
+iio:device0/in_voltage_3_raw = 5
+iio:device0/in_voltage_4_raw = 7
+iio:device0/in_voltage_5_raw = 9
+
+[uart]
+ttySAC4 = 34, 36
+
+[spi]
+spidev2.0 = 19, 21, 23, 25
--- /dev/null
+[gpio]
+gpio4 = 7
+gpio5 = 29
+gpio6 = 31
+gpio12 = 15
+gpio13 = 33
+gpio17 = 11
+gpio18 = 12
+gpio22 = 15
+gpio24 = 18
+gpio25 = 22
+gpio26 = 37
+gpio27 = 12
+
+[i2c]
+i2c-1 = 5, 3
+
+[pwm]
+
+[adc]
+
+[uart]
+
+[spi]
+spidev0.0 = 24, 23, 21, 19
+spidev0.1 = 26, 23, 21, 19
+spidev1.0 = 36, 40, 35, 38
+
--- /dev/null
+[gpio]
+;gpio4 = 7
+
+[i2c]
+;i2c-1 = 5, 3
+
+[pwm]
+;pwmchip0/pwm2 = 30
+
+[adc]
+;iio:device0/in_voltage_0_raw = 40
+
+[uart]
+;ttySAC4 = 34, 36
+
+[spi]
+;spidev0.0 = 24, 23, 21, 19
BuildRequires: pkgconfig(gio-2.0)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(capi-system-peripheral-io)
+BuildRequires: pkgconfig(iniparser)
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
cp %{SOURCE2} ./
%build
+export CFLAGS="$CFLAGS -DSYSCONFDIR=\\\"%{_sysconfdir}\\\""
MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
%cmake . -DMAJORVER=${MAJORVER} -DFULLVER=%{version}
install -m 0644 %SOURCE2 %{buildroot}%{_unitdir}/peripheral-bus.service
%install_service multi-user.target.wants peripheral-bus.service
+mkdir -p %{buildroot}/etc/peripheral-bus
+cp %{_builddir}/%{name}-%{version}/data/*.ini %{buildroot}/etc/%{name}
+
%post
systemctl daemon-reload
if [ $1 == 1 ]; then
%{_bindir}/peripheral-bus
%{_unitdir}/peripheral-bus.service
%{_unitdir}/multi-user.target.wants/peripheral-bus.service
+/etc/peripheral-bus/*.ini
}
pb_data->adc_path = NULL;
+ pb_data->board = peripheral_bus_board_init();
+ if (pb_data->board == NULL) {
+ _E("failed to init board");
+ return -1;
+ }
owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
PERIPHERAL_GDBUS_NAME,
g_main_loop_run(loop);
if (pb_data) {
+ peripheral_bus_board_deinit(pb_data->board);
if (pb_data->adc_path)
free(pb_data->adc_path);
free(pb_data);
#include <gio/gio.h>
#include "peripheral_io_gdbus.h"
+#include "peripheral_bus_board.h"
typedef enum {
PERIPHERAL_BUS_TYPE_GPIO = 0,
} peripheral_bus_type_e;
typedef struct {
+ pb_board_s *board;
/* daemon variable */
char *adc_path;
/* devices */
--- /dev/null
+/*
+ * 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 <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <iniparser.h>
+
+#include <peripheral_io.h>
+
+#include "peripheral_bus_board.h"
+#include "peripheral_common.h"
+
+#define STR_BUF_MAX 255
+
+#define BOARD_INI_ARTIK710_PATH SYSCONFDIR"/peripheral-bus/pio_board_artik710.ini"
+#define BOARD_INI_RP3_B_12_PATH SYSCONFDIR"/peripheral-bus/pio_board_rp3_b_12.ini"
+#define BOARD_INI_UNKNOWN_PATH SYSCONFDIR"/peripheral-bus/pio_board_unknown.ini"
+
+static const pb_board_type_s pb_board_type[] = {
+ {PB_BOARD_ARTIK710, "artik710 raptor", BOARD_INI_ARTIK710_PATH},
+ {PB_BOARD_ARTIK530, "artik530 raptor", BOARD_INI_ARTIK710_PATH},
+ {PB_BOARD_RP3_B_12, "Raspberry Pi 3 Model B Rev 1.2", BOARD_INI_RP3_B_12_PATH},
+ {PB_BOARD_UNKOWN, "unkown board", BOARD_INI_UNKNOWN_PATH},
+};
+
+static int peripheral_bus_board_get_device_type(char *string)
+{
+ if (0 == strncmp(string, "gpio", strlen("gpio")))
+ return PB_BOARD_DEV_GPIO;
+ else if (0 == strncmp(string, "i2c", strlen("i2c")))
+ return PB_BOARD_DEV_I2C;
+ else if (0 == strncmp(string, "pwm", strlen("pwm")))
+ return PB_BOARD_DEV_PWM;
+ else if (0 == strncmp(string, "adc", strlen("adc")))
+ return PB_BOARD_DEV_ADC;
+ else if (0 == strncmp(string, "uart", strlen("uart")))
+ return PB_BOARD_DEV_UART;
+ else if (0 == strncmp(string, "spi", strlen("spi")))
+ return PB_BOARD_DEV_SPI;
+
+ return -1;
+}
+
+static void peripheral_bus_board_ini_parse_key(pb_board_dev_e type, char *string, unsigned int *args)
+{
+ switch (type) {
+ case PB_BOARD_DEV_GPIO:
+ sscanf(string, "%*50[^0-9]%d", &args[0]);
+ break;
+ case PB_BOARD_DEV_I2C:
+ sscanf(string, "%*50[^-]-%d", &args[0]);
+ break;
+ case PB_BOARD_DEV_PWM:
+ sscanf(string, "%*50[^0-9]%d%*50[^0-9]%d", &args[0], &args[1]);
+ break;
+ case PB_BOARD_DEV_ADC:
+ sscanf(string, "%*50[^0-9]%d%*50[^0-9]%d", &args[0], &args[1]);
+ break;
+ case PB_BOARD_DEV_UART:
+ sscanf(string, "%*50[^0-9]%d", &args[0]);
+ break;
+ case PB_BOARD_DEV_SPI:
+ sscanf(string, "%*50[^0-9]%d.%d", &args[0], &args[1]);
+ break;
+ default:
+ break;
+ }
+}
+
+static int peripheral_bus_board_ini_parse_pins(char *string, unsigned int *pins)
+{
+ const char delimiter[] = ", ";
+ int cnt_pins = 0;
+ char *token, *ptr = NULL;
+
+ if (string == NULL) return 0;
+
+ token = strtok_r(string, delimiter, &ptr);
+ while (token) {
+ if (cnt_pins >= BOARD_PINS_MAX) break;
+
+ pins[cnt_pins++] = atoi(token);
+ token = strtok_r(NULL, delimiter, &ptr);
+ }
+
+ return cnt_pins;
+}
+
+static int peripheral_bus_board_ini_get_nkeys(dictionary *dict)
+{
+ int i, sec_num, key_num, ret = 0;
+ char *section;
+
+ sec_num = iniparser_getnsec(dict);
+ for (i = 0; i < sec_num; i++) {
+ section = iniparser_getsecname(dict, i);
+ key_num = iniparser_getsecnkeys(dict, section);
+ if (key_num <= 0) continue;
+ ret += key_num;
+ }
+
+ return ret;
+}
+
+static int peripheral_bus_board_get_type(void)
+{
+ int fd, i;
+ char str_buf[STR_BUF_MAX] = {0};
+ int type = PB_BOARD_UNKOWN;
+
+ fd = open(BOARD_DEVICE_TREE, O_RDONLY);
+ if (fd < 0) {
+ strerror_r(errno, str_buf, STR_BUF_MAX);
+ _E("Cannot open %s, errmsg : %s", BOARD_DEVICE_TREE, str_buf);
+ return -ENXIO;
+ }
+
+ if (read(fd, str_buf, STR_BUF_MAX) < 0) {
+ _E("Failed to read model information, path : %s", BOARD_DEVICE_TREE);
+ close(fd);
+ return -EIO;
+ }
+
+ for (i = 0; i < PB_BOARD_UNKOWN; i++) {
+ if (strstr(str_buf, pb_board_type[i].name)) {
+ type = pb_board_type[i].type;
+ break;
+ }
+ }
+
+ close(fd);
+
+ return type;
+}
+
+static pb_board_s *peripheral_bus_board_get_info()
+{
+ dictionary *dict = NULL;
+ int i, j, ret;
+ int sec_num, key_num, cnt_key = 0;
+ char *section, *key_str;
+ char **key_list = NULL;
+ pb_board_dev_s *dev;
+ pb_board_dev_e enum_dev;
+ pb_board_s *board;
+
+ board = (pb_board_s*)calloc(1, sizeof(pb_board_s));
+ if (board == NULL) {
+ _E("Failed to allocate pb_board_s");
+ return NULL;
+ }
+
+ ret = peripheral_bus_board_get_type();
+ if (ret < 0) {
+ _E("Failed to get board type");
+ goto err_get_type;
+ }
+
+ board->type = (pb_board_type_e)ret;
+ dict = iniparser_load(pb_board_type[board->type].path);
+ if (dict == NULL) {
+ _E("Failed to load %s", pb_board_type[board->type].path);
+ goto err_get_type;
+ }
+
+ board->num_dev = peripheral_bus_board_ini_get_nkeys(dict);
+ if (board->num_dev == 0) {
+ _E("There is no device to open");
+ goto err_get_nkeys;
+ }
+
+ board->dev = calloc(board->num_dev, sizeof(pb_board_dev_s));
+ if (board->dev == NULL) {
+ _E("Failed to allocate pb_board_dev_s");
+ goto err_get_nkeys;
+ }
+
+ sec_num = iniparser_getnsec(dict);
+ for (i = 0; i < sec_num; i++) {
+ section = iniparser_getsecname(dict, i);
+ ret = peripheral_bus_board_get_device_type(section);
+ if (ret < 0) continue;
+
+ enum_dev = (pb_board_dev_e)ret;
+ key_list = iniparser_getseckeys(dict, section);
+ key_num = iniparser_getsecnkeys(dict, section);
+ if (key_num <= 0) continue;
+
+ for (j = 0; j < key_num; j++) {
+ dev = &board->dev[cnt_key];
+ dev->dev_type = enum_dev;
+ key_str = iniparser_getstring(dict, key_list[j], NULL);
+ peripheral_bus_board_ini_parse_key(dev->dev_type, key_list[j], dev->args);
+ dev->num_pins = peripheral_bus_board_ini_parse_pins(key_str, dev->pins);
+ cnt_key++;
+ }
+ }
+
+ iniparser_freedict(dict);
+
+ return board;
+
+err_get_nkeys:
+ iniparser_freedict(dict);
+
+err_get_type:
+ free(board);
+ return NULL;
+}
+
+pb_board_dev_s *peripheral_bus_board_find_device(pb_board_dev_e dev_type, pb_board_s *board, int arg, ...)
+{
+ int i, args[2] = {0, };
+ va_list ap;
+
+ RETV_IF(board == NULL, false);
+
+ args[0] = arg;
+ if (dev_type == PB_BOARD_DEV_PWM || dev_type == PB_BOARD_DEV_ADC || dev_type == PB_BOARD_DEV_SPI) {
+ va_start(ap, arg);
+ args[1] = va_arg(ap, int);
+ va_end(ap);
+ }
+
+ for (i = 0; i < board->num_dev; i++) {
+ if (board->dev[i].dev_type != dev_type) continue;
+
+ if (board->dev[i].args[0] == args[0] && board->dev[i].args[1] == args[1])
+ return &board->dev[i];
+ }
+
+ return NULL;
+}
+
+pb_board_s *peripheral_bus_board_init(void)
+{
+ pb_board_s *board;
+
+ board = peripheral_bus_board_get_info();
+
+ return board;
+}
+
+void peripheral_bus_board_deinit(pb_board_s *board)
+{
+ if (board) {
+ if (board->dev)
+ free(board->dev);
+
+ free(board);
+ }
+}
--- /dev/null
+/*
+ * 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_BOARD_H__
+#define __PERIPHERAL_BUS_BOARD_H__
+
+#define BOARD_DEVICE_TREE "/proc/device-tree/model"
+#define BOARD_PINS_MAX 4
+#define BOARD_ARGS_MAX 2
+
+typedef enum {
+ PB_BOARD_ARTIK710 = 0,
+ PB_BOARD_ARTIK530,
+ PB_BOARD_RP3_B_12,
+ PB_BOARD_UNKOWN,
+} pb_board_type_e;
+
+typedef enum {
+ PB_BOARD_DEV_GPIO = 0,
+ PB_BOARD_DEV_I2C,
+ PB_BOARD_DEV_PWM,
+ PB_BOARD_DEV_ADC,
+ PB_BOARD_DEV_UART,
+ PB_BOARD_DEV_SPI,
+ PB_BOARD_DEV_MAX,
+} pb_board_dev_e;
+
+typedef struct {
+ pb_board_type_e type;
+ char *name;
+ char *path;
+} pb_board_type_s;
+
+typedef struct {
+ pb_board_dev_e dev_type;
+ unsigned int pins[BOARD_PINS_MAX];
+ unsigned int num_pins;
+ unsigned int args[BOARD_ARGS_MAX];
+} pb_board_dev_s;
+
+typedef struct {
+ pb_board_type_e type;
+ pb_board_dev_s *dev;
+ unsigned int num_dev;
+} pb_board_s;
+
+pb_board_dev_s *peripheral_bus_board_find_device(pb_board_dev_e dev_type, pb_board_s *board, int arg, ...);
+pb_board_s *peripheral_bus_board_init(void);
+void peripheral_bus_board_deinit(pb_board_s *board);
+
+#endif /* __PERIPHERAL_BUS_BOARD_H__ */
#include "peripheral_common.h"
#include "peripheral_bus_util.h"
-static bool peripheral_bus_gpio_is_available(int pin, GList *list)
+static bool peripheral_bus_gpio_is_available(int pin, peripheral_bus_s *pb_data)
{
+ pb_board_dev_s *gpio = NULL;
+ pb_data_h handle;
GList *link;
- pb_data_h handle = NULL;
- link = list;
+ RETV_IF(pb_data == NULL, false);
+ RETV_IF(pb_data->board == NULL, false);
+
+ gpio = peripheral_bus_board_find_device(PB_BOARD_DEV_GPIO, pb_data->board, pin);
+ if (gpio == NULL) {
+ _E("Not supported GPIO pin : %d", pin);
+ return false;
+ }
+
+ link = pb_data->gpio_list;
while (link) {
handle = (pb_data_h)link->data;
- if (handle->dev.gpio.pin == pin)
+ if (handle->dev.gpio.pin == pin) {
+ _E("gpio %d is busy", pin);
return false;
+ }
link = g_list_next(link);
}
int edge, direction;
int ret;
- if (!peripheral_bus_gpio_is_available(pin, pb_data->gpio_list)) {
- _E("gpio %d is busy", pin);
+ if (!peripheral_bus_gpio_is_available(pin, pb_data)) {
+ _E("gpio %d is not available", pin);
return PERIPHERAL_ERROR_RESOURCE_BUSY;
}
#define INITIAL_BUFFER_SIZE 128
#define MAX_BUFFER_SIZE 8192
-static bool peripheral_bus_i2c_is_available(int bus, int address, GList *list)
+static bool peripheral_bus_i2c_is_available(int bus, int address, peripheral_bus_s *pb_data)
{
- GList *link;
+ pb_board_dev_s *i2c = NULL;
pb_data_h handle;
+ GList *link;
+
+ RETV_IF(pb_data == NULL, false);
+ RETV_IF(pb_data->board == NULL, false);
- link = list;
+ i2c = peripheral_bus_board_find_device(PB_BOARD_DEV_I2C, pb_data->board, bus);
+ if (i2c == NULL) {
+ _E("Not supported I2C bus : %d", bus);
+ return false;
+ }
+
+ link = pb_data->i2c_list;
while (link) {
handle = (pb_data_h)link->data;
- if (handle->dev.i2c.bus == bus && handle->dev.i2c.address == address)
+ if (handle->dev.i2c.bus == bus && handle->dev.i2c.address == address) {
+ _E("Resource is in use, bus : %d, address : %d", bus, address);
return false;
+ }
link = g_list_next(link);
}
int ret;
int fd;
- if (!peripheral_bus_i2c_is_available(bus, address, pb_data->i2c_list)) {
- _E("Resource is in use, bus : %d, address : %d", bus, address);
+ if (!peripheral_bus_i2c_is_available(bus, address, pb_data)) {
+ _E("i2c %d (address : %X) is not available", bus, address);
return PERIPHERAL_ERROR_RESOURCE_BUSY;
}
#include "peripheral_common.h"
#include "peripheral_bus_util.h"
-static bool peripheral_bus_pwm_is_available(int device, int channel, GList *list)
+static bool peripheral_bus_pwm_is_available(int device, int channel, peripheral_bus_s *pb_data)
{
- GList *link;
+ pb_board_dev_s *pwm = NULL;
pb_data_h handle;
+ GList *link;
+
+ RETV_IF(pb_data == NULL, false);
+ RETV_IF(pb_data->board == NULL, false);
+
+ pwm = peripheral_bus_board_find_device(PB_BOARD_DEV_PWM, pb_data->board, device, channel);
+ if (pwm == NULL) {
+ _E("Not supported PWM device : %d, channel : %d", device, channel);
+ return false;
+ }
- link = list;
+ link = pb_data->pwm_list;
while (link) {
handle = (pb_data_h)link->data;
- if (handle->dev.pwm.device == device && handle->dev.pwm.channel == channel)
+ if (handle->dev.pwm.device == device && handle->dev.pwm.channel == channel) {
+ _E("Resource is in use, device : %d, channel : %d", device, channel);
return false;
+ }
link = g_list_next(link);
}
pb_data_h pwm_handle;
int ret;
- if (!peripheral_bus_pwm_is_available(device, channel, pb_data->pwm_list)) {
- _E("Resource is in use, device : %d, channel : %d", device, channel);
+ if (!peripheral_bus_pwm_is_available(device, channel, pb_data)) {
+ _E("pwm %d.%d is not available", device, channel);
return PERIPHERAL_ERROR_RESOURCE_BUSY;
}
static int initial_buffer_size = 128;
static int max_buffer_size = 4096;
-static bool peripheral_bus_spi_is_available(int bus, int cs, GList *list)
+static bool peripheral_bus_spi_is_available(int bus, int cs, peripheral_bus_s *pb_data)
{
- GList *link;
+ pb_board_dev_s *spi = NULL;
pb_data_h handle;
+ GList *link;
+
+ RETV_IF(pb_data == NULL, false);
+ RETV_IF(pb_data->board == NULL, false);
- link = list;
+ spi = peripheral_bus_board_find_device(PB_BOARD_DEV_SPI, pb_data->board, bus, cs);
+ if (spi == NULL) {
+ _E("Not supported SPI bus : %d, cs : %d", bus, cs);
+ return false;
+ }
+
+ link = pb_data->spi_list;
while (link) {
handle = (pb_data_h)link->data;
- if (handle->dev.spi.bus == bus && handle->dev.spi.cs == cs)
+ if (handle->dev.spi.bus == bus && handle->dev.spi.cs == cs) {
+ _E("Resource is in use, bus : %d, cs : %d", bus, cs);
return false;
+ }
link = g_list_next(link);
}
int ret = PERIPHERAL_ERROR_NONE;
int fd, bufsiz;
- if (!peripheral_bus_spi_is_available(bus, cs, pb_data->spi_list)) {
- _E("Resource is in use, bus : %d, cs : %d", bus, cs);
+ if (!peripheral_bus_spi_is_available(bus, cs, pb_data)) {
+ _E("spi %d.%d is not available", bus, cs);
return PERIPHERAL_ERROR_RESOURCE_BUSY;
}
#define INITIAL_BUFFER_SIZE 128
#define MAX_BUFFER_SIZE 8192
-static bool peripheral_bus_uart_is_available(int port, GList *list)
+static bool peripheral_bus_uart_is_available(int port, peripheral_bus_s *pb_data)
{
- GList *link;
+ pb_board_dev_s *uart = NULL;
pb_data_h handle;
+ GList *link;
+
+ RETV_IF(pb_data == NULL, false);
+ RETV_IF(pb_data->board == NULL, false);
+
+ uart = peripheral_bus_board_find_device(PB_BOARD_DEV_UART, pb_data->board, port);
+ if (uart == NULL) {
+ _E("Not supported UART port : %d", port);
+ return false;
+ }
- link = list;
+ link = pb_data->uart_list;
while (link) {
handle = (pb_data_h)link->data;
- if (handle->dev.uart.port == port)
+ if (handle->dev.uart.port == port) {
+ _E("Resource is in use, port : %d", port);
return false;
+ }
link = g_list_next(link);
}
int ret = PERIPHERAL_ERROR_NONE;
int fd;
- if (!peripheral_bus_uart_is_available(port, pb_data->uart_list)) {
- _E("Resource is in use, port : %d", port);
+ if (!peripheral_bus_uart_is_available(port, pb_data)) {
+ _E("uart %d is not available", port);
return PERIPHERAL_ERROR_RESOURCE_BUSY;
}