|
@@ -29,6 +29,141 @@
|
|
|
#include <gpiod.h>
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
+#define USESYSFS
|
|
|
+
|
|
|
+#ifdef USESYSFS
|
|
|
+#include <errno.h>
|
|
|
+
|
|
|
+#define UART0Mode1 190
|
|
|
+#define UART0Mode0 191
|
|
|
+#define UART0Enable 192
|
|
|
+#define UART0Terminate 193
|
|
|
+
|
|
|
+int gpio_export(int gpio)
|
|
|
+{
|
|
|
+ int efd;
|
|
|
+ char buf[50];
|
|
|
+ int gpiofd, ret;
|
|
|
+
|
|
|
+ /* Quick test if it has already been exported */
|
|
|
+ sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
|
|
|
+ efd = open(buf, O_WRONLY);
|
|
|
+ if(efd != -1) {
|
|
|
+ close(efd);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ efd = open("/sys/class/gpio/export", O_WRONLY | O_SYNC);
|
|
|
+
|
|
|
+ if(efd != -1) {
|
|
|
+ sprintf(buf, "%d", gpio);
|
|
|
+ ret = write(efd, buf, strlen(buf));
|
|
|
+ if(ret < 0) {
|
|
|
+ perror("Export failed");
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+ close(efd);
|
|
|
+ } else {
|
|
|
+ // If we can't open the export file, we probably
|
|
|
+ // dont have any gpio permissions
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void gpio_unexport(int gpio)
|
|
|
+{
|
|
|
+ int gpiofd, ret;
|
|
|
+ char buf[50];
|
|
|
+ gpiofd = open("/sys/class/gpio/unexport", O_WRONLY | O_SYNC);
|
|
|
+ sprintf(buf, "%d", gpio);
|
|
|
+ ret = write(gpiofd, buf, strlen(buf));
|
|
|
+ close(gpiofd);
|
|
|
+}
|
|
|
+
|
|
|
+int gpio_direction(int gpio, int dir)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ char buf[50];
|
|
|
+ sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);
|
|
|
+ int gpiofd = open(buf, O_WRONLY | O_SYNC);
|
|
|
+ if(gpiofd < 0) {
|
|
|
+ perror("Couldn't open direction file");
|
|
|
+ ret = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(dir == 2 && gpiofd){
|
|
|
+ if (4 != write(gpiofd, "high", 4)) {
|
|
|
+ fprintf(stderr, "Couldn't set GPIO %d direction to out/high: %s\n",
|
|
|
+ gpio,
|
|
|
+ strerror(errno));
|
|
|
+ ret = -2;
|
|
|
+ }
|
|
|
+ } else if(dir == 1 && gpiofd){
|
|
|
+ if (3 != write(gpiofd, "out", 3)) {
|
|
|
+ fprintf(stderr, "Couldn't set GPIO %d direction to out/low: %s\n",
|
|
|
+ gpio,
|
|
|
+ strerror(errno));
|
|
|
+ ret = -3;
|
|
|
+ }
|
|
|
+ } else if(gpiofd) {
|
|
|
+ if(2 != write(gpiofd, "in", 2)) {
|
|
|
+ fprintf(stderr, "Couldn't set GPIO %d direction to in: %s\n",
|
|
|
+ gpio,
|
|
|
+ strerror(errno));
|
|
|
+ ret = -4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ close(gpiofd);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int gpio_read(int gpio)
|
|
|
+{
|
|
|
+ char in[3] = {0, 0, 0};
|
|
|
+ char buf[50];
|
|
|
+ int nread, gpiofd;
|
|
|
+ sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
|
|
|
+ gpiofd = open(buf, O_RDWR | O_SYNC);
|
|
|
+ if(gpiofd < 0) {
|
|
|
+ fprintf(stderr, "Failed to open gpio %d value\n", gpio);
|
|
|
+ perror("gpio failed");
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ nread = read(gpiofd, in, 1);
|
|
|
+ } while (nread == 0);
|
|
|
+ if(nread == -1){
|
|
|
+ perror("GPIO Read failed");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ close(gpiofd);
|
|
|
+ return atoi(in);
|
|
|
+}
|
|
|
+
|
|
|
+int gpio_write(int gpio, int val)
|
|
|
+{
|
|
|
+ char buf[50];
|
|
|
+ int nread, ret, gpiofd;
|
|
|
+ sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);
|
|
|
+ gpiofd = open(buf, O_RDWR);
|
|
|
+ if(gpiofd > 0) {
|
|
|
+ snprintf(buf, 2, "%d", val ? 1 : 0);
|
|
|
+ ret = write(gpiofd, buf, 2);
|
|
|
+ if(ret < 0) {
|
|
|
+ perror("failed to set gpio");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ close(gpiofd);
|
|
|
+ if(ret == 2) return 0;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
typedef unsigned char BYTE;
|
|
|
typedef unsigned int UINT;
|
|
|
typedef unsigned short U16;
|
|
@@ -205,18 +340,39 @@ void gpio_set(const char *line_name, int value)
|
|
|
|
|
|
static void gpio_set_mode(int mode0, int mode1)
|
|
|
{
|
|
|
+#ifdef USESYSFS
|
|
|
+ gpio_export(UART0Enable);
|
|
|
+ gpio_direction(UART0Enable, 1);
|
|
|
+ gpio_write(UART0Enable, 1);
|
|
|
+
|
|
|
+ gpio_export(UART0Mode0);
|
|
|
+ gpio_direction(UART0Mode0, 1);
|
|
|
+ gpio_write(UART0Mode0, mode0);
|
|
|
+
|
|
|
+ gpio_export(UART0Mode1);
|
|
|
+ gpio_direction(UART0Mode1, 1);
|
|
|
+ gpio_write(UART0Mode1, mode1);
|
|
|
+#else
|
|
|
gpio_set("UART0-enable", 1);
|
|
|
gpio_set("UART0-mode0", mode0);
|
|
|
gpio_set("UART0-mode1", mode1);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
static void gpio_set_terminate(int onoff)
|
|
|
{
|
|
|
+#ifdef USESYSFS
|
|
|
+ gpio_export(UART0Terminate);
|
|
|
+ gpio_direction(UART0Terminate, 1);
|
|
|
+ gpio_write(UART0Terminate, onoff);
|
|
|
+#else
|
|
|
gpio_set("UART0-terminate", onoff);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
static void gpio_switch_mode(const char *mode, int terminate)
|
|
|
{
|
|
|
+
|
|
|
if(compare_string(mode, "rs232", e_case_insensitive))
|
|
|
{
|
|
|
gpio_set_mode(1, 0);
|
|
@@ -250,6 +406,7 @@ static void gpio_switch_mode(const char *mode, int terminate)
|
|
|
}while(0)
|
|
|
|
|
|
#define GET_UART_RTS_ACTIVE_LOGIC(flags) (!((flags) & SER_RS485_RTS_ON_SEND))
|
|
|
+#define GET_UART_RTS_ACTIVE_LOGIC_SET(flags) (((flags) & (SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND)))
|
|
|
|
|
|
static E_STATUS ttyuart_get_rs485conf(const char *uartdev, struct serial_rs485 *pcfg)
|
|
|
{
|
|
@@ -291,7 +448,7 @@ static void ttyuart_print_mode(const char *uartdev)
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if(rs485conf.flags & SER_RS485_RX_DURING_TX)
|
|
|
+ if(rs485conf.flags & SER_RS485_RX_DURING_TX && !(GET_UART_RTS_ACTIVE_LOGIC_SET(rs485conf.flags)))
|
|
|
{
|
|
|
mode = "rs422";
|
|
|
activelogic = "";
|
|
@@ -342,7 +499,7 @@ static E_STATUS ttyuart_switchto_rs232(const char *uartdev)
|
|
|
return ttyuart_set_rs485conf(uartdev, &rs485conf);
|
|
|
}
|
|
|
|
|
|
-static E_STATUS ttyuart_switchto_rs485(const char *uartdev, int logicLevel)
|
|
|
+static E_STATUS ttyuart_switchto_rs485(const char *uartdev, int logicLevel, int terminate)
|
|
|
{
|
|
|
struct serial_rs485 rs485conf;
|
|
|
memset(&rs485conf, 0, sizeof(rs485conf));
|
|
@@ -350,6 +507,7 @@ static E_STATUS ttyuart_switchto_rs485(const char *uartdev, int logicLevel)
|
|
|
SET_UART_RTS_ACTIVE_LOGIC(rs485conf.flags, logicLevel);
|
|
|
|
|
|
rs485conf.flags |= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
|
|
|
+ if(terminate) rs485conf.flags |= SER_RS485_TERMINATE_BUS;
|
|
|
|
|
|
return ttyuart_set_rs485conf(uartdev, &rs485conf);
|
|
|
}
|
|
@@ -387,6 +545,8 @@ static void ttyuart_command_handle(int argc, char **argv)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ const int terminate = check_arg(argc, argv, "-t,--terminate", e_case_sensitive);
|
|
|
+
|
|
|
if(check_arg(argc, argv, "-d,--display", e_case_sensitive))
|
|
|
{
|
|
|
ttyuart_print_mode(devType);
|
|
@@ -405,14 +565,17 @@ static void ttyuart_command_handle(int argc, char **argv)
|
|
|
if(0 == strcasecmp(mode, "rs232"))
|
|
|
{
|
|
|
ttyuart_switchto_rs232(devType);
|
|
|
+ gpio_switch_mode(mode, 0);
|
|
|
}
|
|
|
else if(0 == strcasecmp(mode, "rs485"))
|
|
|
{
|
|
|
- ttyuart_switchto_rs485(devType, logicLevel);
|
|
|
+ ttyuart_switchto_rs485(devType, logicLevel, terminate);
|
|
|
+ gpio_switch_mode(mode, terminate);
|
|
|
}
|
|
|
else if(0 == strcasecmp(mode, "rs422"))
|
|
|
{
|
|
|
ttyuart_switchto_rs422(devType);
|
|
|
+ gpio_switch_mode(mode, 0);
|
|
|
}
|
|
|
else
|
|
|
{
|