ES-2024 reverter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
2.2 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include <termios.h>
  7. #include "context.h"
  8. #include "event.h"
  9. #include "logging.h"
  10. #include "statemachine.h"
  11. struct serial_device {
  12. struct termios oldtio;
  13. struct termios newtio;
  14. };
  15. static int open_serial(struct context *ctx, const char *devname)
  16. {
  17. struct serial_device *sdev = (struct serial_device *)ctx->dev_privdata;
  18. ctx->fd = open(devname, O_RDWR);
  19. if (ctx->fd < 0) {
  20. log_print(LOG_ERROR, "open_serial(): open(%s)", devname);
  21. return -1;
  22. }
  23. ctx->devname = strdup(devname);
  24. if (tcgetattr(ctx->fd, &sdev->oldtio) != 0) {
  25. log_print(LOG_WARN, "open_serial(): tcgetattr()");
  26. close(ctx->fd);
  27. return -1;
  28. }
  29. bzero(&sdev->newtio, sizeof(struct termios));
  30. sdev->newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
  31. tcflush(ctx->fd, TCIOFLUSH);
  32. if (tcsetattr(ctx->fd, TCSANOW, &sdev->newtio) != 0) {
  33. log_print(LOG_WARN, "open_serial(): tcsetattr()");
  34. close(ctx->fd);
  35. return -1;
  36. }
  37. return 0;
  38. }
  39. static int setbaudrate(struct context *ctx, int baudrate)
  40. {
  41. struct serial_device *sdev = (struct serial_device *)ctx->dev_privdata;
  42. cfsetispeed(&sdev->newtio, baudrate);
  43. cfsetospeed(&sdev->newtio, baudrate);
  44. /* flush linebuffer */
  45. ctx->linepos = 0;
  46. if (tcsetattr(ctx->fd, TCSANOW, &sdev->newtio) != 0) {
  47. log_print(LOG_WARN, "open_serial(): tcsetattr()");
  48. close(ctx->fd);
  49. return -1;
  50. }
  51. return 0;
  52. }
  53. static int close_serial(struct context *ctx)
  54. {
  55. struct serial_device *sdev = (struct serial_device *)ctx->dev_privdata;
  56. event_remove_fd(ctx->event);
  57. tcsetattr(ctx->fd, TCSANOW, &sdev->oldtio);
  58. free(ctx->devname);
  59. close(ctx->fd);
  60. return 0;
  61. }
  62. int serial_init(struct context *ctx, const char *device)
  63. {
  64. ctx->dev_privdata = malloc(sizeof(struct serial_device));
  65. if (ctx->dev_privdata == NULL) {
  66. log_print(LOG_WARN, "serial_init_cb(): out of memory");
  67. destroy_context(ctx);
  68. return -1;
  69. }
  70. if (open_serial(ctx, device) < 0) {
  71. free(ctx->dev_privdata);
  72. destroy_context(ctx);
  73. return -1;
  74. }
  75. log_print(LOG_EVERYTIME, "listen on %s", ctx->devname);
  76. ctx->dev_close = close_serial;
  77. ctx->dev_setbaudrate = setbaudrate;
  78. ctx->event = event_add_readfd(NULL, ctx->fd, statemachine_read, ctx);
  79. return 0;
  80. }