switchserialmode.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright (c) Siemens AG, 2017
  3. *
  4. * Authors:
  5. * Sascha Weisenberger <sascha.weisenberger@siemens.com>
  6. * Jan Kiszka <jan.kiszka@siemens.com>
  7. *
  8. * This file is subject to the terms and conditions of the MIT License. See
  9. * COPYING.MIT file in the top-level directory.
  10. */
  11. #include <linux/serial.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <fcntl.h>
  15. #include <sys/ioctl.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #ifndef SER_RS485_TERMINATE_BUS
  20. #define SER_RS485_TERMINATE_BUS (1 << 5)
  21. #endif
  22. static void print_usage(char *name)
  23. {
  24. printf("Usage: %s DEVICE [MODE [-t|--terminate]]\n"
  25. "\n"
  26. "DEVICE\t\tThe device for which you want to switch the mode.\n"
  27. "MODE\t\tThe mode you want to use: rs232, rs485, or rs422.\n"
  28. "\t\tIf omitted, the current mode will be printed.\n"
  29. "\n"
  30. "Optional arguments:\n"
  31. " -t, --terminate\tTerminate the RS422 or RS485 bus.\n"
  32. "\n"
  33. "Example: %s /dev/ttyS2 rs485 --terminate\n", name, name);
  34. }
  35. static void print_mode(struct serial_rs485 *rs485conf)
  36. {
  37. const char *mode, *terminate;
  38. if (!(rs485conf->flags & SER_RS485_ENABLED)) {
  39. mode = "RS232";
  40. terminate = "";
  41. } else {
  42. if (rs485conf->flags & SER_RS485_RX_DURING_TX)
  43. mode = "RS422";
  44. else
  45. mode = "RS485";
  46. if (rs485conf->flags & SER_RS485_TERMINATE_BUS)
  47. terminate = ", terminating";
  48. else
  49. terminate = ", non-terminating";
  50. }
  51. printf("%s%s\n", mode, terminate);
  52. }
  53. static int get_mode(int file, char *device)
  54. {
  55. struct serial_rs485 rs485conf;
  56. if (ioctl(file, TIOCGRS485, &rs485conf) < 0) {
  57. perror("Error");
  58. return 1;
  59. }
  60. printf("Mode of %s: ", device);
  61. print_mode(&rs485conf);
  62. return 0;
  63. }
  64. static int set_mode(int file, char *device, char *mode, char *option)
  65. {
  66. struct serial_rs485 rs485conf;
  67. rs485conf.flags = 0;
  68. if (strcasecmp("rs485", mode) == 0) {
  69. rs485conf.flags |= SER_RS485_ENABLED;
  70. } else if (strcasecmp("rs422", mode) == 0) {
  71. rs485conf.flags |= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
  72. } else if (strcasecmp("rs232", mode) != 0) {
  73. fprintf(stderr, "Invalid mode \"%s\"\n", mode);
  74. return 2;
  75. }
  76. if (option) {
  77. if (strcmp(option, "-t") == 0 ||
  78. strcmp(option, "--terminate") == 0) {
  79. if (!(rs485conf.flags & SER_RS485_ENABLED)) {
  80. fprintf(stderr,
  81. "Termination not supported in RS232 "
  82. "mode\n");
  83. return 2;
  84. }
  85. rs485conf.flags |= SER_RS485_TERMINATE_BUS;
  86. } else {
  87. fprintf(stderr, "Invalid option \"%s\"\n", option);
  88. return 2;
  89. }
  90. }
  91. if (ioctl(file, TIOCSRS485, &rs485conf) < 0) {
  92. perror("Error");
  93. return 1;
  94. }
  95. printf("Successfully set %s to ", device);
  96. print_mode(&rs485conf);
  97. return 0;
  98. }
  99. int main(int argc, char *argv[])
  100. {
  101. int file, ret;
  102. if (argc < 2 || argc > 4) {
  103. print_usage(argv[0]);
  104. return 2;
  105. }
  106. if (!strcmp(argv[1], "--help")) {
  107. print_usage(argv[0]);
  108. return 0;
  109. }
  110. file = open(argv[1], O_RDWR);
  111. if (file < 0) {
  112. perror("Error");
  113. return 1;
  114. }
  115. if (argc == 2)
  116. ret = get_mode(file, argv[1]);
  117. else
  118. ret = set_mode(file, argv[1], argv[2], argv[3]);
  119. close(file);
  120. return ret;
  121. }