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.
 
 
 
 
 
 

183 lines
4.0 KiB

  1. /*
  2. * Copyright (C) 2016-2017 by Marc Schink
  3. * openocd-dev@marcschink.de
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <stdint.h>
  19. #include <rtt/rtt.h>
  20. #include "server.h"
  21. #include "rtt_server.h"
  22. /**
  23. * @file
  24. *
  25. * RTT server.
  26. *
  27. * This server allows access to Real Time Transfer (RTT) channels via TCP
  28. * connections.
  29. */
  30. struct rtt_service {
  31. unsigned int channel;
  32. };
  33. static int read_callback(unsigned int channel, const uint8_t *buffer,
  34. size_t length, void *user_data)
  35. {
  36. int ret;
  37. struct connection *connection;
  38. size_t offset;
  39. connection = (struct connection *)user_data;
  40. offset = 0;
  41. while (offset < length) {
  42. ret = connection_write(connection, buffer + offset, length - offset);
  43. if (ret < 0) {
  44. LOG_ERROR("Failed to write data to socket.");
  45. return ERROR_FAIL;
  46. }
  47. offset += ret;
  48. }
  49. return ERROR_OK;
  50. }
  51. static int rtt_new_connection(struct connection *connection)
  52. {
  53. int ret;
  54. struct rtt_service *service;
  55. service = connection->service->priv;
  56. LOG_DEBUG("New connection for RTT channel %u", service->channel);
  57. ret = rtt_register_sink(service->channel, &read_callback, connection);
  58. if (ret != ERROR_OK)
  59. return ret;
  60. return ERROR_OK;
  61. }
  62. static int rtt_connection_closed(struct connection *connection)
  63. {
  64. struct rtt_service *service;
  65. service = (struct rtt_service *)connection->service->priv;
  66. rtt_unregister_sink(service->channel, &read_callback, connection);
  67. LOG_DEBUG("Connection for RTT channel %u closed", service->channel);
  68. return ERROR_OK;
  69. }
  70. static int rtt_input(struct connection *connection)
  71. {
  72. int bytes_read;
  73. unsigned char buffer[1024];
  74. struct rtt_service *service;
  75. size_t length;
  76. service = (struct rtt_service *)connection->service->priv;
  77. bytes_read = connection_read(connection, buffer, sizeof(buffer));
  78. if (!bytes_read)
  79. return ERROR_SERVER_REMOTE_CLOSED;
  80. else if (bytes_read < 0) {
  81. LOG_ERROR("error during read: %s", strerror(errno));
  82. return ERROR_SERVER_REMOTE_CLOSED;
  83. }
  84. length = bytes_read;
  85. rtt_write_channel(service->channel, buffer, &length);
  86. return ERROR_OK;
  87. }
  88. COMMAND_HANDLER(handle_rtt_start_command)
  89. {
  90. int ret;
  91. struct rtt_service *service;
  92. if (CMD_ARGC != 2)
  93. return ERROR_COMMAND_SYNTAX_ERROR;
  94. service = malloc(sizeof(struct rtt_service));
  95. if (!service)
  96. return ERROR_FAIL;
  97. COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
  98. ret = add_service("RTT", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED,
  99. rtt_new_connection, rtt_input, rtt_connection_closed, service);
  100. if (ret != ERROR_OK) {
  101. free(service);
  102. return ERROR_FAIL;
  103. }
  104. return ERROR_OK;
  105. }
  106. COMMAND_HANDLER(handle_rtt_stop_command)
  107. {
  108. if (CMD_ARGC != 1)
  109. return ERROR_COMMAND_SYNTAX_ERROR;
  110. remove_service("RTT", CMD_ARGV[0]);
  111. return ERROR_OK;
  112. }
  113. static const struct command_registration rtt_subcommand_handlers[] = {
  114. {
  115. .name = "start",
  116. .handler = handle_rtt_start_command,
  117. .mode = COMMAND_ANY,
  118. .help = "Start a RTT server",
  119. .usage = "<port> <channel>"
  120. },
  121. {
  122. .name = "stop",
  123. .handler = handle_rtt_stop_command,
  124. .mode = COMMAND_ANY,
  125. .help = "Stop a RTT server",
  126. .usage = "<port>"
  127. },
  128. COMMAND_REGISTRATION_DONE
  129. };
  130. static const struct command_registration rtt_command_handlers[] = {
  131. {
  132. .name = "rttserver",
  133. .mode = COMMAND_ANY,
  134. .help = "RTT server",
  135. .usage = "",
  136. .chain = rtt_subcommand_handlers
  137. },
  138. COMMAND_REGISTRATION_DONE
  139. };
  140. int rtt_server_register_commands(struct command_context *ctx)
  141. {
  142. return register_commands(ctx, NULL, rtt_command_handlers);
  143. }