From: Segwon Date: Mon, 13 Nov 2017 04:30:38 +0000 (+0900) Subject: [1/6] fd passing: move interface code from daemon. X-Git-Tag: submit/tizen_4.0/20171220.125806^2~41 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c606f0ab36778e64b5da531bf1e2704195dfb38e;p=platform%2Fcore%2Fapi%2Fperipheral-io.git [1/6] fd passing: move interface code from daemon. - move from "peripheral-bus/src/interface/" - in order to improve performance, the lib area has direct access to the kernel. - not yet include in the build. Signed-off-by: Segwon Change-Id: Id3a047968f7018ef352b01aa93cb0450ecda1f4d --- diff --git a/src/interface/gpio.c b/src/interface/gpio.c new file mode 100644 index 0000000..77c73c8 --- /dev/null +++ b/src/interface/gpio.c @@ -0,0 +1,373 @@ +/* + * 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 +#include +#include +#include +#include + +#include "gpio.h" +#include "peripheral_common.h" + +#define MAX_ERR_LEN 255 + +int gpio_open(int gpiopin) +{ + int fd, len, status; + char gpio_export[GPIO_BUFFER_MAX] = {0, }; + + _D("gpiopin : %d", gpiopin); + + fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/export :%s\n", errmsg); + return -ENXIO; + } + + len = snprintf(gpio_export, GPIO_BUFFER_MAX, "%d", gpiopin); + status = write(fd, gpio_export, len); + + if (status != len) { + close(fd); + _E("Error: gpio open error \n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_set_direction(int gpiopin, gpio_direction_e dir) +{ + int fd, status; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + + _D("gpiopin : %d, dir : %d", gpiopin, dir); + + snprintf(gpio_dev, GPIO_BUFFER_MAX, SYSFS_GPIO_DIR"/gpio%d/direction", gpiopin); + fd = open(gpio_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d/direction: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + if (dir == GPIO_DIRECTION_IN) + status = write(fd, "in", strlen("in")+1); + else if (dir == GPIO_DIRECTION_OUT_HIGH) + status = write(fd, "high", strlen("high")+1); + else if (dir == GPIO_DIRECTION_OUT_LOW) + status = write(fd, "low", strlen("low")+1); + else { + close(fd); + _E("Error: gpio direction is wrong\n"); + return -EIO; + } + + if (status <= 0) { + close(fd); + _E("Error: gpio direction set error\n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_get_direction(int gpiopin, gpio_direction_e *dir) +{ + int fd, len; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + char gpio_buf[GPIO_BUFFER_MAX] = {0, }; + + snprintf(gpio_dev, GPIO_BUFFER_MAX, SYSFS_GPIO_DIR"/gpio%d/direction", gpiopin); + fd = open(gpio_dev, O_RDONLY); + + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d/direction: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + len = read(fd, &gpio_buf, GPIO_BUFFER_MAX); + if (len <= 0) { + close(fd); + _E("Error: gpio direction read error\n"); + return -EIO; + } + + if (0 == strncmp(gpio_buf, "in", strlen("in"))) + *dir = GPIO_DIRECTION_IN; + else if (0 == strncmp(gpio_buf, "out", strlen("out"))) + *dir = GPIO_DIRECTION_OUT_LOW; + else { + close(fd); + _E("Error: gpio direction is wrong\n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_set_edge_mode(int gpiopin, gpio_edge_e edge) +{ + int fd, status; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + + _D("gpiopin : %d, edge : %d", gpiopin, edge); + + snprintf(gpio_dev, GPIO_BUFFER_MAX, SYSFS_GPIO_DIR"/gpio%d/edge", gpiopin); + fd = open(gpio_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d/edge: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + if (edge == GPIO_EDGE_NONE) + status = write(fd, "none", strlen("none")+1); + else if (edge == GPIO_EDGE_RISING) + status = write(fd, "rising", strlen("rising")+1); + else if (edge == GPIO_EDGE_FALLING) + status = write(fd, "falling", strlen("falling")+1); + else if (edge == GPIO_EDGE_BOTH) + status = write(fd, "both", strlen("both")+1); + else { + close(fd); + _E("Error: gpio edge is wrong\n"); + return -EIO; + } + + if (status <= 0) { + close(fd); + _E("Error: gpio edge set error\n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_get_edge_mode(int gpiopin, gpio_edge_e *edge) +{ + int fd, len; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + char gpio_buf[GPIO_BUFFER_MAX] = {0, }; + + snprintf(gpio_dev, GPIO_BUFFER_MAX, SYSFS_GPIO_DIR"/gpio%d/edge", gpiopin); + fd = open(gpio_dev, O_RDONLY); + + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d/edge: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + len = read(fd, &gpio_buf, GPIO_BUFFER_MAX); + if (len <= 0) { + close(fd); + _E("Error: gpio edge read error\n"); + return -EIO; + } + + if (0 == strncmp(gpio_buf, "none", strlen("none"))) + *edge = GPIO_EDGE_NONE; + else if (0 == strncmp(gpio_buf, "both", strlen("both"))) + *edge = GPIO_EDGE_BOTH; + else if (0 == strncmp(gpio_buf, "rising", strlen("rising"))) + *edge = GPIO_EDGE_RISING; + else if (0 == strncmp(gpio_buf, "falling", strlen("falling"))) + *edge = GPIO_EDGE_FALLING; + else { + close(fd); + _E("Error: gpio edge is wrong\n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_write(int gpiopin, int value) +{ + int fd, status; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + + snprintf(gpio_dev, GPIO_BUFFER_MAX, SYSFS_GPIO_DIR"/gpio%d/value", gpiopin); + fd = open(gpio_dev, O_WRONLY); + + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d/value: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + if (value == 1) + status = write(fd, "1", strlen("1")+1); + else if (value == 0) + status = write(fd, "0", strlen("0")+1); + else { + close(fd); + _E("Error: gpio write value error \n"); + return -EIO; + } + + if (status <= 0) { + close(fd); + _E("Error: gpio write error\n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_read(int gpiopin, int *value) +{ + int fd, len; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + char gpio_buf[GPIO_BUFFER_MAX] = {0, }; + + snprintf(gpio_dev, GPIO_BUFFER_MAX, SYSFS_GPIO_DIR"/gpio%d/value", gpiopin); + fd = open(gpio_dev, O_RDONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d pin value: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + len = read(fd, &gpio_buf, 1); + close(fd); + + if (len <= 0) { + _E("Error: gpio read error \n"); + return -EIO; + } + + if (0 == strncmp(gpio_buf, "1", strlen("1"))) + *value = 1; + else if (0 == strncmp(gpio_buf, "0", strlen("0"))) + *value = 0; + else { + _E("Error: gpio value is error \n"); + return -EIO; + } + + return 0; +} + +int gpio_close(int gpiopin) +{ + int fd, len, status; + char gpio_unexport[GPIO_BUFFER_MAX] = {0, }; + + _D("gpiopin : %d", gpiopin); + + fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/unexport %s\n", errmsg); + return -ENXIO; + } + + len = snprintf(gpio_unexport, GPIO_BUFFER_MAX, "%d", gpiopin); + status = write(fd, gpio_unexport, len); + + if (status != len) { + close(fd); + _E("Error: gpio close error \n"); + return -EIO; + } + + close(fd); + + return 0; +} + +int gpio_open_isr(int gpiopin) +{ + int fd; + char gpio_dev[GPIO_BUFFER_MAX] = {0, }; + + snprintf(gpio_dev, sizeof(gpio_dev)-1, SYSFS_GPIO_DIR"/gpio%d/value", gpiopin); + + _D("open isr string [%s]", gpio_dev); + + fd = open(gpio_dev, O_RDONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open /sys/class/gpio/gpio%d pin value: %s\n", gpiopin, errmsg); + return -ENXIO; + } + + return fd; +} + +int gpio_close_isr(int fd) +{ + if (fd <= 0) return -EINVAL; + + close(fd); + + return 0; +} + +int gpio_read_isr(void *fdset, char *rev_buf, int length) +{ + int poll_state = 0; + int len; + struct pollfd poll_events; + + poll_events.fd = ((struct pollfd*)fdset)->fd; + poll_events.events = POLLPRI; + poll_events.revents = ((struct pollfd*)fdset)->revents; + + poll_state = poll((struct pollfd*)&poll_events, 1, -1); // 0 is going to return directly. + + if (poll_state < 0) { + _E("poll() failed!\n"); + return -EIO; + } + + if (poll_events.revents & POLLPRI) { + lseek(poll_events.fd, 0, SEEK_SET); + len = read(poll_events.fd, rev_buf, length); + if (len == -1) + return -EIO; + } + + return poll_state; +} diff --git a/src/interface/i2c.c b/src/interface/i2c.c new file mode 100644 index 0000000..0907cce --- /dev/null +++ b/src/interface/i2c.c @@ -0,0 +1,136 @@ +/* + * 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 +#include +#include +#include +#include + +#include "i2c.h" +#include "peripheral_common.h" + +#define MAX_ERR_LEN 255 + +int i2c_open(int bus, int *fd) +{ + int new_fd; + char i2c_dev[I2C_BUFFER_MAX] = {0,}; + + _D("bus : %d", bus); + + snprintf(i2c_dev, sizeof(i2c_dev)-1, SYSFS_I2C_DIR"-%d", bus); + new_fd = open(i2c_dev, O_RDWR); + if (new_fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s : %s", i2c_dev, errmsg); + return -ENXIO; + } + _D("fd : %d", new_fd); + *fd = new_fd; + + return 0; +} + +int i2c_close(int fd) +{ + int status; + + _D("fd : %d", fd); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + 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 i2c_set_address(int fd, int address) +{ + int status; + + _D("fd : %d, slave address : 0x%x", fd, address); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + status = ioctl(fd, I2C_SLAVE, address); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to set slave address(%x), fd : %d, errmsg : %s", address, fd, errmsg); + return status; + } + + return 0; +} + +int i2c_read(int fd, unsigned char *data, int length) +{ + int status; + + RETVM_IF(fd < 0, -EINVAL, "Invalid fd : %d", fd); + + status = read(fd, data, length); + if (status != length) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("i2c read failed, fd : %d, errmsg : %s", fd, errmsg); + return -EIO; + } + + return 0; +} + +int i2c_write(int fd, const unsigned char *data, int length) +{ + int status; + + RETVM_IF(fd < 0, -EINVAL, "Invalid fd : %d", fd); + + status = write(fd, data, length); + if (status != length) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("i2c write failed fd : %d, errmsg : %s", fd, errmsg); + return -EIO; + } + + return 0; +} + +int i2c_smbus_ioctl(int fd, struct i2c_smbus_ioctl_data *data) +{ + int status; + + RETVM_IF(fd < 0, -EINVAL, "Invalid fd : %d", fd); + + status = ioctl(fd, I2C_SMBUS, data); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("i2c transaction failed fd : %d, errmsg : %s", fd, errmsg); + return -EIO; + } + + return 0; +} diff --git a/src/interface/include/gpio.h b/src/interface/include/gpio.h new file mode 100644 index 0000000..b0b7c5b --- /dev/null +++ b/src/interface/include/gpio.h @@ -0,0 +1,48 @@ +/* + * 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 __GPIO_H__ +#define __GPIO_H__ + +#define SYSFS_GPIO_DIR "/sys/class/gpio" +#define GPIO_BUFFER_MAX 64 + +typedef enum { + GPIO_DIRECTION_IN = 0, + GPIO_DIRECTION_OUT_HIGH = 1, + GPIO_DIRECTION_OUT_LOW = 2, +} gpio_direction_e; + +typedef enum { + GPIO_EDGE_NONE = 0, + GPIO_EDGE_RISING = 1, + GPIO_EDGE_FALLING = 2, + GPIO_EDGE_BOTH = 3, +} gpio_edge_e; + +int gpio_open(int gpiopin); +int gpio_close(int gpiopin); +int gpio_set_edge_mode(int gpiopin, gpio_edge_e edge); +int gpio_get_edge_mode(int gpiopin, gpio_edge_e *edge); +int gpio_set_direction(int gpiopin, gpio_direction_e dir); +int gpio_get_direction(int gpiopin, gpio_direction_e *dir); +int gpio_write(int gpiopin, int value); +int gpio_read(int gpiopin, int *value); + +int gpio_open_isr(int gpiopin); +int gpio_close_isr(int file_hndl); +int gpio_read_isr(void *fdset, char *rev_buf, int length); +#endif/*__GPIO_H__*/ diff --git a/src/interface/include/i2c.h b/src/interface/include/i2c.h new file mode 100644 index 0000000..f0d4668 --- /dev/null +++ b/src/interface/include/i2c.h @@ -0,0 +1,65 @@ +/* + * 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 __I2C_H__ +#define __I2C_H__ + +#include + +#define SYSFS_I2C_DIR "/dev/i2c" +#define I2C_BUFFER_MAX 64 + +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_SMBUS 0x0720 /* SMBus transfer */ + +/* i2c_smbus_xfer read or write markers */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 + +/* + * Data for SMBus Messages + */ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ + +union i2c_smbus_data { + uint8_t byte; + uint16_t word; + uint8_t block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ + /* and one more for user-space compatibility */ +}; + +/* This is the structure as used in the I2C_SMBUS ioctl call */ +struct i2c_smbus_ioctl_data { + uint8_t read_write; + uint8_t command; + uint32_t size; + union i2c_smbus_data *data; +}; + +int i2c_open(int bus, int *fd); +int i2c_close(int fd); +int i2c_set_address(int fd, int address); +int i2c_read(int fd, unsigned char *data, int length); +int i2c_write(int fd, const unsigned char *data, int length); +int i2c_smbus_ioctl(int fd, struct i2c_smbus_ioctl_data *data); + +#endif/* __I2C_H__ */ diff --git a/src/interface/include/pwm.h b/src/interface/include/pwm.h new file mode 100644 index 0000000..26243d3 --- /dev/null +++ b/src/interface/include/pwm.h @@ -0,0 +1,125 @@ +/* + * 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 __PWM_H__ +#define __PWM_H__ + +/** + * @brief Enumeration for Polarity + */ +typedef enum { + PWM_POLARITY_NORMAL = 0, + PWM_POLARITY_INVERSED, +} pwm_polarity_e; + +/** +* @brief pwm_open() init pwm pin. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_open(int chip, int pin); + +/** +* @brief pwm_close() deinit pwm pin. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_close(int chip, int pin); + +/** +* @brief pwm_set_period() sets the pwm period. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[in] period pwm period +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_set_period(int chip, int pin, int period); + +/** +* @brief pwm_get_period() gets the pwm period. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[out] period pwm period +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_get_period(int chip, int pin, int *period); + +/** +* @brief pwm_set_duty_cycle() sets the pwm duty cycle. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[in] duty_cycle pwm duty cycle +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_set_duty_cycle(int chip, int pin, int duty_cycle); + +/** +* @brief pwm_get_duty_cycle() gets the pwm duty cycle. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[out] duty_cycle pwm duty cycle +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_get_duty_cycle(int chip, int pin, int *duty_cycle); + +/** +* @brief pwm_set_polarity() sets the pwm polarity. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[in] polarity pwm polarity +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_set_polarity(int chip, int pin, pwm_polarity_e polarity); +/** +* @brief pwm_get_polarity() gets the pwm polarity. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[out] polarity pwm polarity +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_get_polarity(int chip, int pin, pwm_polarity_e *polarity); + +/** +* @brief pwm_set_enable() sets the pwm state. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[in] enable pwm enable/disabled state value +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_set_enable(int chip, int pin, bool enable); + +/** +* @brief pwm_get_enable() checks if pwm state is enabled. +* +* @param[in] chip pwm chip number +* @param[in] pin pwm pin number +* @param[out] enable pwm enable/disabled state value +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int pwm_get_enable(int chip, int pin, bool *enable); + +#endif /* __PWM_H__ */ diff --git a/src/interface/include/spi.h b/src/interface/include/spi.h new file mode 100644 index 0000000..9937c41 --- /dev/null +++ b/src/interface/include/spi.h @@ -0,0 +1,31 @@ +/* + * 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 __SPI_H__ +#define __SPI_H__ + +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_set_bit_order(int fd, unsigned char lsb); +int spi_set_bits_per_word(int fd, unsigned char bits); +int spi_set_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_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int length); + +#endif /* __SPI_H__ */ diff --git a/src/interface/include/uart.h b/src/interface/include/uart.h new file mode 100644 index 0000000..413b23e --- /dev/null +++ b/src/interface/include/uart.h @@ -0,0 +1,185 @@ +/* + * 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 __UART_H__ +#define __UART_H__ + +#include + +/** + * @brief Enumeration for Baud Rate + */ +typedef enum { + UART_BAUD_RATE_0 = 0, + UART_BAUD_RATE_50, + UART_BAUD_RATE_75, + UART_BAUD_RATE_110, + UART_BAUD_RATE_134, + UART_BAUD_RATE_150, + UART_BAUD_RATE_200, + UART_BAUD_RATE_300, + UART_BAUD_RATE_600, + UART_BAUD_RATE_1200, + UART_BAUD_RATE_1800, + UART_BAUD_RATE_2400, + UART_BAUD_RATE_4800, + UART_BAUD_RATE_9600, + UART_BAUD_RATE_19200, + UART_BAUD_RATE_38400, + UART_BAUD_RATE_57600, + UART_BAUD_RATE_115200, + UART_BAUD_RATE_230400 +} uart_baud_rate_e; + +/** + * @brief Enumeration for Byte Size + */ +typedef enum { + UART_BYTE_SIZE_5BIT = 0, + UART_BYTE_SIZE_6BIT, + UART_BYTE_SIZE_7BIT, + UART_BYTE_SIZE_8BIT +} uart_byte_size_e; + +/** + * @brief Enumeration of Parity Bit + */ +typedef enum { + UART_PARITY_NONE = 0, + UART_PARITY_EVEN, + UART_PARITY_ODD +} uart_parity_e; + +/** + * @brief Enumeration for Stop Bits + */ +typedef enum { + UART_STOP_BITS_1BIT = 0, + UART_STOP_BITS_2BIT +} uart_stop_bits_e; + +/** +* @brief uart_valid_baudrate() validation check of input baudrate +* +* @param[in] baudrate baudrate for uart +* @return On success, valid input. On failure, NULL is returned. +*/ +int uart_valid_baud_rate(unsigned int baud_rate); + +/** +* @brief uart_open() initializes uart port. +* +* @param[in] port uart port +* @param[in] file_hndl handle of uart port +* @return On success, handle of uart_context is returned. On failure, NULL is returned. +*/ +int uart_open(int port, int *file_hndl); + +/** +* @brief uart_close() closes uart port. +* +* @param[in] file_hndl handle of uart_context +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_close(int file_hndl); + +/** +* @brief uart_flush() flushes uart buffer. +* +* @param[in] file_hndl handle of uart_context +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_flush(int file_hndl); + +/** +* @brief uart_set_baudrate() sets uart baud rate. +* +* @param[in] file_hndl handle of uart_context +* @param[in] baud uart baud rate +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_set_baud_rate(int file_hndl, uart_baud_rate_e baud); + +/** +* @brief uart_set_mode() sets byte size, parity bit and stop bits. +* +* @param[in] file_hndl handle of uart_context +* @param[in] byte_size uart byte size +* @param[in] parity uart parity type (even/odd/none) +* @param[in] stop_bits uart stop bits +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_set_mode(int file_hndl, uart_byte_size_e byte_size, uart_parity_e parity, uart_stop_bits_e stop_bits); + +/** +* @brief peripheral_bus_uart_set_byte_size() set byte size. +* +* @param[in] file_hndl handle of uart_context +* @param[in] byte_size uart byte size +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_set_byte_size(int file_hndl, uart_byte_size_e byte_size); + +/** +* @brief peripheral_bus_uart_set_parity() set parity bit. +* +* @param[in] file_hndl handle of uart_context +* @param[in] parity uart parity type (even/odd/none) +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_set_parity(int file_hndl, uart_parity_e parity); + +/** +* @brief peripheral_bus_uart_set_stop_bits() set stop bits. +* +* @param[in] file_hndl handle of uart_context +* @param[in] stop_bits uart stop bits +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_set_stop_bits(int file_hndl, uart_stop_bits_e stop_bits); + +/** +* @brief uart_set_flow_control() set flow control settings. +* +* @param[in] file_hndl handle of uart_context +* @param[in] xonxoff ixon/ixoff +* @param[in] rtscts rts/cts +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_set_flow_control(int file_hndl, bool xonxoff, bool rtscts); + +/** +* @brief uart_read() reads data over uart bus. +* +* @param[in] file_hndl handle of uart_context +* @param[in] buf the pointer of data buffer +* @param[in] length size to read +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_read(int file_hndl, uint8_t *buf, unsigned int length); + +/** +* @brief uart_write() writes data over uart bus. +* +* @param[in] file_hndl handle of uart_context +* @param[in] buf the pointer of data buffer +* @param[in] length size to write +* @return On success, 0 is returned. On failure, a negative value is returned. +*/ +int uart_write(int file_hndl, uint8_t *buf, unsigned int length); + +#endif /* __UART_H__ */ + diff --git a/src/interface/pwm.c b/src/interface/pwm.c new file mode 100644 index 0000000..2b6ebd8 --- /dev/null +++ b/src/interface/pwm.c @@ -0,0 +1,334 @@ +/* + * 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 +#include +#include +#include +#include + +#include "pwm.h" +#include "peripheral_common.h" + +#define SYSFS_PWM_PATH "/sys/class/pwm" + +#define PATH_BUF_MAX 64 +#define PWM_BUF_MAX 16 +#define MAX_ERR_LEN 255 + +int pwm_open(int chip, int pin) +{ + int fd, len, status; + char pwm_dev[PATH_BUF_MAX] = {0}; + char pwm_buf[PWM_BUF_MAX] = {0}; + + _D("chip : %d, pin : %d", chip, pin); + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/export", chip); + fd = open(pwm_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + len = snprintf(pwm_buf, sizeof(pwm_buf), "%d", pin); + status = write(fd, pwm_buf, len); + if (status < 0) { + _E("Failed to export pwmchip%d, pwm%d", chip, pin); + close(fd); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_close(int chip, int pin) +{ + int fd, len, status; + char pwm_dev[PATH_BUF_MAX] = {0}; + char pwm_buf[PWM_BUF_MAX] = {0}; + + _D("chip : %d, pin : %d", chip, pin); + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/unexport", chip); + fd = open(pwm_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + len = snprintf(pwm_buf, sizeof(pwm_buf), "%d", pin); + status = write(fd, pwm_buf, len); + if (status < 0) { + _E("Failed to unexport pwmchip%d, pwm%", chip, pin); + close(fd); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_set_period(int chip, int pin, int period) +{ + int fd, len, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + _D("chip : %d, pin : %d, period : %d", chip, pin, period); + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/period", chip, pin); + fd = open(pwm_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + len = snprintf(pwm_buf, sizeof(pwm_buf), "%d", period); + status = write(fd, pwm_buf, len); + if (status < 0) { + close(fd); + _E("Failed to set period, path : %s", pwm_dev); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_get_period(int chip, int pin, int *period) +{ + int fd, result, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/period", chip, pin); + fd = open(pwm_dev, O_RDONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + status = read(fd, pwm_buf, PWM_BUF_MAX); + if (status < 0) { + close(fd); + _E("Failed to get period, path : %s", pwm_dev); + return -EIO; + } + result = atoi(pwm_buf); + *period = result; + close(fd); + + return 0; +} + +int pwm_set_duty_cycle(int chip, int pin, int duty_cycle) +{ + int fd, len, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + _D("chip : %d, pin : %d, duty_cycle : %d", chip, pin, duty_cycle); + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/duty_cycle", chip, pin); + fd = open(pwm_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + len = snprintf(pwm_buf, sizeof(pwm_buf), "%d", duty_cycle); + status = write(fd, pwm_buf, len); + if (status < 0) { + close(fd); + _E("Failed to set duty cycle, path : %s", pwm_dev); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_get_duty_cycle(int chip, int pin, int *duty_cycle) +{ + int fd, result, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/duty_cycle", chip, pin); + fd = open(pwm_dev, O_RDONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + status = read(fd, pwm_buf, PWM_BUF_MAX); + if (status < 0) { + close(fd); + _E("Failed to get duty cycle, path : %s", pwm_dev); + return -EIO; + } + result = atoi(pwm_buf); + *duty_cycle = result; + close(fd); + + return 0; +} + +int pwm_set_polarity(int chip, int pin, pwm_polarity_e polarity) +{ + int fd, status; + char pwm_dev[PATH_BUF_MAX] = {0}; + + _D("chip : %d, pin : %d, polarity : %d", chip, pin, polarity); + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/polarity", chip, pin); + fd = open(pwm_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + if (polarity == PWM_POLARITY_NORMAL) + status = write(fd, "normal", strlen("normal")+1); + else if (polarity == PWM_POLARITY_INVERSED) + status = write(fd, "inversed", strlen("inversed")+1); + else { + _E("Invalid pwm polarity : %d", polarity); + close(fd); + return -EINVAL; + } + + if (status <= 0) { + close(fd); + _E("Failed to set polarity, path : %s", pwm_dev); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_get_polarity(int chip, int pin, pwm_polarity_e *polarity) +{ + int fd, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/polarity", chip, pin); + fd = open(pwm_dev, O_RDONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + status = read(fd, pwm_buf, PWM_BUF_MAX); + if (status < 0) { + _E("Failed to get polarity, path : %s", pwm_dev); + close(fd); + return -EIO; + } + + if (0 == strncmp(pwm_buf, "normal", strlen("normal"))) + *polarity = PWM_POLARITY_NORMAL; + else if (0 == strncmp(pwm_buf, "inversed", strlen("inversed"))) + *polarity = PWM_POLARITY_INVERSED; + else { + close(fd); + _E("Invalid pwm polarity : %d", pwm_buf); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_set_enable(int chip, int pin, bool enable) +{ + int fd, len, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + _D("chip : %d, pin : %d, enable : %d", chip, pin, enable); + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/enable", chip, pin); + fd = open(pwm_dev, O_WRONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + len = snprintf(pwm_buf, sizeof(pwm_buf), "%d", enable); + status = write(fd, pwm_buf, len); + if (status < 0) { + close(fd); + _E("Failed to set enable, path : %s", pwm_dev); + return -EIO; + } + close(fd); + + return 0; +} + +int pwm_get_enable(int chip, int pin, bool *enable) +{ + int fd, result, status; + char pwm_buf[PWM_BUF_MAX] = {0}; + char pwm_dev[PATH_BUF_MAX] = {0}; + + snprintf(pwm_dev, PATH_BUF_MAX, SYSFS_PWM_PATH "/pwmchip%d/pwm%d/enable", chip, pin); + fd = open(pwm_dev, O_RDONLY); + if (fd < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Can't Open %s, errmsg : %s", pwm_dev, errmsg); + return -ENXIO; + } + + status = read(fd, pwm_buf, PWM_BUF_MAX); + if (status < 0) { + close(fd); + _E("Failed to get enable, path : %s", pwm_dev); + return -EIO; + } + result = atoi(pwm_buf); + *enable = !!result; + close(fd); + + return 0; +} + diff --git a/src/interface/spi.c b/src/interface/spi.c new file mode 100644 index 0000000..1016a9e --- /dev/null +++ b/src/interface/spi.c @@ -0,0 +1,239 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "spi.h" +#include "peripheral_common.h" + +#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 new_fd = 0; + char spi_dev[SPI_BUFFER_MAX] = {0,}; + + _D("bus : %d, cs : %d", bus, cs); + + snprintf(spi_dev, sizeof(spi_dev)-1, SYSFS_SPI_DIR"%d.%d", bus, cs); + + 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 -ENXIO; + } + _D("fd : %d", new_fd); + *fd = new_fd; + + return 0; +} + +int spi_close(int fd) +{ + int status; + + _D("fd : %d", fd); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + 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 fd, unsigned char mode) +{ + int status; + + _D("fd : %d, mode : %d", fd, mode); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + status = ioctl(fd, SPI_IOC_WR_MODE, &mode); + if (status < 0) { + 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_bit_order(int fd, unsigned char lsb) +{ + int status; + + _D("fd : %d, lsb : %d", fd, lsb); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + status = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to set lsb first(%d), fd : %d, errmsg : %s", lsb, fd, errmsg); + return -EIO; + } + + return 0; +} + +int spi_set_bits_per_word(int fd, unsigned char bits) +{ + int status; + + _D("fd : %d, bits : %d", fd, bits); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + status = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to set bits(%d), fd : %d, errmsg : %s", bits, fd, errmsg); + return -EIO; + } + + return 0; +} + +int spi_set_frequency(int fd, unsigned int freq) +{ + int status; + + _D("fd : %d, freq : %d", fd, freq); + RETVM_IF(fd < 0, -EINVAL, "Invalid fd"); + + status = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &freq); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to set frequency(%d), fd : %d, errmsg : %s", freq, fd, errmsg); + return -EIO; + } + + return 0; +} + +int spi_get_buffer_size(int *bufsiz) +{ + 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 -ENXIO; + } + + status = read(fd, spi_buf, SPI_BUFFER_MAX); + if (status < 0) { + _E("Failed to get buffer size, path : %s", SYSFS_SPI_BUFSIZ); + close(fd); + return -EIO; + } + result = atoi(spi_buf); + *bufsiz = result; + close(fd); + + return 0; +} + +int spi_read(int fd, unsigned char *rxbuf, int length) +{ + int status; + struct spi_ioc_transfer xfer; + + RETVM_IF(fd < 0, -EINVAL, "Invalid fd : %d", fd); + + memset(&xfer, 0, sizeof(struct spi_ioc_transfer)); + xfer.rx_buf = (unsigned long)rxbuf; + xfer.len = length; + + status = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to read data, fd : %d, length : %d, errmsg : %s", fd, length, errmsg); + return -EIO; + } + + return 0; +} + +int spi_write(int fd, unsigned char *txbuf, int length) +{ + int status; + struct spi_ioc_transfer xfer; + + RETVM_IF(fd < 0, -EINVAL, "Invalid fd : %d", fd); + + memset(&xfer, 0, sizeof(struct spi_ioc_transfer)); + xfer.tx_buf = (unsigned long)txbuf; + xfer.len = length; + + status = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer); + if (status < 0) { + 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_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int length) +{ + int status; + struct spi_ioc_transfer xfer; + + RETVM_IF(fd < 0, -EINVAL, "Invalid fd : %d", fd); + + if (!txbuf || !rxbuf || length < 0) return -EINVAL; + + memset(&xfer, 0, sizeof(xfer)); + xfer.tx_buf = (unsigned long)txbuf; + xfer.rx_buf = (unsigned long)rxbuf; + xfer.len = length; + + status = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer); + if (status < 0) { + 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; +} diff --git a/src/interface/uart.c b/src/interface/uart.c new file mode 100644 index 0000000..34ff11e --- /dev/null +++ b/src/interface/uart.c @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "uart.h" +#include "peripheral_common.h" + +#define PATH_BUF_MAX 64 +#define UART_BUF_MAX 16 + +#define UART_BAUDRATE_SIZE 19 + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif +#define MAX_ERR_LEN 128 + +char *sysfs_uart_path[] = { + "/dev/ttyS", + "/dev/ttyAMA", + "/dev/ttySAC", +}; + +static const int peripheral_uart_br[UART_BAUDRATE_SIZE] = { + B0, B50, B75, B110, B134, + B150, B200, B300, B600, B1200, + B1800, B2400, B4800, B9600, B19200, + B38400, B57600, B115200, B230400 +}; + +static const int byteinfo[4] = {CS5, CS6, CS7, CS8}; + +int uart_open(int port, int *file_hndl) +{ + int i, fd; + char uart_dev[PATH_BUF_MAX] = {0}; + + _D("port : %d", port); + + for (i = 0; i < ARRAY_SIZE(sysfs_uart_path); i++) { + snprintf(uart_dev, PATH_BUF_MAX, "%s%d", sysfs_uart_path[i], port); + if (access(uart_dev, F_OK) == 0) + break; + } + _D("uart_dev : %s", uart_dev); + if ((fd = open(uart_dev, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("can't open %s, errmsg : %s", uart_dev, errmsg); + return -ENXIO; + } + *file_hndl = fd; + return 0; +} + +int uart_close(int file_hndl) +{ + int status; + + _D("file_hndl : %d", file_hndl); + + if (file_hndl < 0) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + status = uart_flush(file_hndl); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to close fd : %d, errmsg : %s", file_hndl, errmsg); + return -EIO; + } + + status = close(file_hndl); + if (status < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("Failed to close fd : %d, errmsg : %s", file_hndl, errmsg); + return -EIO; + } + + return 0; +} + +int uart_flush(int file_hndl) +{ + int ret; + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + ret = tcflush(file_hndl, TCIOFLUSH); + if (ret < 0) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcflush failed, errmsg : %s", errmsg); + return -1; + } + + return 0; +} + +int uart_set_baud_rate(int file_hndl, uart_baud_rate_e baud) +{ + int ret; + struct termios tio; + + _D("file_hndl : %d, baud : %d", file_hndl, baud); + + memset(&tio, 0, sizeof(tio)); + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + if (baud > UART_BAUD_RATE_230400) { + _E("Invalid parameter"); + return -EINVAL; + } + + ret = tcgetattr(file_hndl, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcgetattr failed, errmsg : %s", errmsg); + return -1; + } + tio.c_cflag = peripheral_uart_br[baud]; + tio.c_iflag = IGNPAR; + tio.c_oflag = 0; + tio.c_lflag = 0; + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + + uart_flush(file_hndl); + ret = tcsetattr(file_hndl, TCSANOW, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcsetattr failed, errmsg: %s", errmsg); + return -1; + } + + return 0; +} + +int uart_set_mode(int file_hndl, uart_byte_size_e byte_size, uart_parity_e parity, uart_stop_bits_e stop_bits) +{ + int ret; + struct termios tio; + + _D("file_hndl : %d, bytesize : %d, parity : %d, stopbits : %d", file_hndl, byte_size, parity, stop_bits); + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + if (byte_size > UART_BYTE_SIZE_8BIT) { + _E("Invalid bytesize parameter"); + return -EINVAL; + } + + ret = tcgetattr(file_hndl, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcgetattr failed, errmsg: %s", errmsg); + return -1; + } + + /* set byte size */ + tio.c_cflag &= ~CSIZE; + tio.c_cflag |= byteinfo[byte_size]; + tio.c_cflag |= (CLOCAL | CREAD); + + /* set parity info */ + switch (parity) { + case UART_PARITY_EVEN: + tio.c_cflag |= PARENB; + tio.c_cflag &= ~PARODD; + break; + case UART_PARITY_ODD: + tio.c_cflag |= PARENB; + tio.c_cflag |= PARODD; + break; + case UART_PARITY_NONE: + default: + tio.c_cflag &= ~PARENB; + tio.c_cflag &= ~PARODD; + break; + } + + /* set stop bit */ + switch (stop_bits) { + case UART_STOP_BITS_1BIT: + tio.c_cflag &= ~CSTOPB; + break; + case UART_STOP_BITS_2BIT: + tio.c_cflag |= CSTOPB; + break; + default: + _E("Invalid parameter stop_bits"); + return -EINVAL; + } + + uart_flush(file_hndl); + ret = tcsetattr(file_hndl, TCSANOW, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcsetattr failed, errmsg : %s", errmsg); + return -1; + } + + return 0; +} + +int uart_set_byte_size(int file_hndl, uart_byte_size_e byte_size) +{ + int ret; + struct termios tio; + + _D("file_hndl : %d, bytesize : %d", file_hndl, byte_size); + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + if (byte_size > UART_BYTE_SIZE_8BIT) { + _E("Invalid bytesize parameter"); + return -EINVAL; + } + + ret = tcgetattr(file_hndl, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcgetattr failed, errmsg: %s", errmsg); + return -1; + } + + /* set byte size */ + tio.c_cflag &= ~CSIZE; + tio.c_cflag |= byteinfo[byte_size]; + tio.c_cflag |= (CLOCAL | CREAD); + + uart_flush(file_hndl); + ret = tcsetattr(file_hndl, TCSANOW, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcsetattr failed, errmsg : %s", errmsg); + return -1; + } + + return 0; +} + +int uart_set_parity(int file_hndl, uart_parity_e parity) +{ + int ret; + struct termios tio; + + _D("file_hndl : %d, parity : %d", file_hndl, parity); + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + ret = tcgetattr(file_hndl, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcgetattr failed, errmsg: %s", errmsg); + return -1; + } + + /* set parity info */ + switch (parity) { + case UART_PARITY_EVEN: + tio.c_cflag |= PARENB; + tio.c_cflag &= ~PARODD; + break; + case UART_PARITY_ODD: + tio.c_cflag |= PARENB; + tio.c_cflag |= PARODD; + break; + case UART_PARITY_NONE: + default: + tio.c_cflag &= ~PARENB; + tio.c_cflag &= ~PARODD; + break; + } + + uart_flush(file_hndl); + ret = tcsetattr(file_hndl, TCSANOW, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcsetattr failed, errmsg : %s", errmsg); + return -1; + } + + return 0; +} + +int uart_set_stop_bits(int file_hndl, uart_stop_bits_e stop_bits) +{ + int ret; + struct termios tio; + + _D("file_hndl : %d, stopbits : %d", file_hndl, stop_bits); + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + ret = tcgetattr(file_hndl, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcgetattr failed, errmsg: %s", errmsg); + return -1; + } + + /* set stop bit */ + switch (stop_bits) { + case UART_STOP_BITS_1BIT: + tio.c_cflag &= ~CSTOPB; + break; + case UART_STOP_BITS_2BIT: + tio.c_cflag |= CSTOPB; + break; + default: + _E("Invalid parameter stop_bits"); + return -EINVAL; + } + + uart_flush(file_hndl); + ret = tcsetattr(file_hndl, TCSANOW, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcsetattr failed, errmsg : %s", errmsg); + return -1; + } + + return 0; +} + +int uart_set_flow_control(int file_hndl, bool xonxoff, bool rtscts) +{ + int ret; + struct termios tio; + + _D("file_hndl : %d, xonxoff : %d, rtscts : %d", file_hndl, xonxoff, rtscts); + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + ret = tcgetattr(file_hndl, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcgetattr failed, errmsg : %s", errmsg); + return -1; + } + + /* rtscts => 1: rts/cts on, 0: off */ + if (rtscts) + tio.c_cflag |= CRTSCTS; + else + tio.c_cflag &= ~CRTSCTS; + + /* xonxoff => 1: xon/xoff on, 0: off */ + if (xonxoff) + tio.c_iflag |= (IXON | IXOFF | IXANY); + else + tio.c_iflag &= ~(IXON | IXOFF | IXANY); + + ret = tcsetattr(file_hndl, TCSANOW, &tio); + if (ret) { + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("tcsetattr failed, errmsg : %s", errmsg); + return -1; + } + + return 0; +} + +int uart_read(int file_hndl, uint8_t *buf, unsigned int length) +{ + int ret; + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + ret = read(file_hndl, (void *)buf, length); + if (ret <= 0) { + if (errno == EAGAIN) + return -EAGAIN; + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("read failed, errmsg : %s", errmsg); + return -EIO; + } + + return ret; +} + +int uart_write(int file_hndl, uint8_t *buf, unsigned int length) +{ + int ret; + + if (!file_hndl) { + _E("Invalid NULL parameter"); + return -EINVAL; + } + + ret = write(file_hndl, buf, length); + if (ret <= 0) { + if (errno == EAGAIN) + return -EAGAIN; + char errmsg[MAX_ERR_LEN]; + strerror_r(errno, errmsg, MAX_ERR_LEN); + _E("write failed, errmsg : %s", errmsg); + return -EIO; + } + + return ret; +}