OpenOCD
rtt_server.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /*
4  * Copyright (C) 2016-2017 by Marc Schink <dev@zapb.de>
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include <stdint.h>
12 #include <rtt/rtt.h>
13 
14 #include "server.h"
15 #include "rtt_server.h"
16 
26 struct rtt_service {
27  unsigned int channel;
29 };
30 
32  unsigned char buffer[64];
33  unsigned int length;
34  unsigned int offset;
35 };
36 
37 static int read_callback(unsigned int channel, const uint8_t *buffer,
38  size_t length, void *user_data)
39 {
40  int ret;
41  struct connection *connection;
42  size_t offset;
43 
44  connection = (struct connection *)user_data;
45  offset = 0;
46 
47  while (offset < length) {
49 
50  if (ret < 0) {
51  LOG_ERROR("Failed to write data to socket.");
52  return ERROR_FAIL;
53  }
54 
55  offset += ret;
56  }
57 
58  return ERROR_OK;
59 }
60 
62 {
63  int ret;
64  struct rtt_service *service;
65  struct rtt_connection_data *data;
66 
67  data = calloc(1, sizeof(struct rtt_connection_data));
68 
69  if (!data) {
70  LOG_ERROR("Out of memory");
71  return ERROR_FAIL;
72  }
73 
74  connection->priv = data;
76 
77  LOG_DEBUG("rtt: New connection for channel %u", service->channel);
78 
80 
81  if (ret != ERROR_OK)
82  return ret;
83 
84  if (service->hello_message)
85  connection_write(connection, service->hello_message, strlen(service->hello_message));
86 
87  return ERROR_OK;
88 }
89 
91 {
92  struct rtt_service *service;
93 
96 
97  free(connection->priv);
98 
99  LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
100  return ERROR_OK;
101 }
102 
103 static int rtt_input(struct connection *connection)
104 {
105  struct rtt_service *service;
106  struct rtt_connection_data *data;
107 
108  data = connection->priv;
110 
111  if (!connection->input_pending) {
112  int bytes_read;
113 
114  bytes_read = connection_read(connection, data->buffer, sizeof(data->buffer));
115 
116  if (!bytes_read) {
118  } else if (bytes_read < 0) {
119  LOG_ERROR("error during read: %s", strerror(errno));
121  }
122 
123  data->length = bytes_read;
124  data->offset = 0;
125  }
126  if (data->length > 0) {
127  unsigned char *ptr;
128  size_t length, to_write;
129 
130  ptr = data->buffer + data->offset;
131  length = data->length - data->offset;
132  to_write = length;
133  rtt_write_channel(service->channel, ptr, &length);
134 
135  if (length < to_write) {
136  data->offset += length;
137  connection->input_pending = true;
138  } else {
139  data->offset = 0;
140  data->length = 0;
141  connection->input_pending = false;
142  }
143  }
144  return ERROR_OK;
145 }
146 
147 static const struct service_driver rtt_service_driver = {
148  .name = "rtt",
149  .new_connection_during_keep_alive_handler = NULL,
150  .new_connection_handler = rtt_new_connection,
151  .input_handler = rtt_input,
152  .connection_closed_handler = rtt_connection_closed,
153  .keep_client_alive_handler = NULL,
154 };
155 
156 COMMAND_HANDLER(handle_rtt_start_command)
157 {
158  int ret;
159  struct rtt_service *service;
160 
161  if (CMD_ARGC < 2 || CMD_ARGC > 3)
163 
164  service = calloc(1, sizeof(struct rtt_service));
165 
166  if (!service) {
167  LOG_ERROR("Out of memory");
168  return ERROR_FAIL;
169  }
170 
171  COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
172 
173  if (CMD_ARGC >= 3) {
174  const char *hello_message = CMD_ARGV[2];
175  size_t hello_length = strlen(hello_message);
176 
177  service->hello_message = malloc(hello_length + 2);
178  if (!service->hello_message) {
179  LOG_ERROR("Out of memory");
180  free(service);
181  return ERROR_FAIL;
182  }
183  strcpy(service->hello_message, hello_message);
184  service->hello_message[hello_length] = '\n';
185  service->hello_message[hello_length + 1] = '\0';
186  }
188 
189  if (ret != ERROR_OK) {
190  free(service);
191  return ERROR_FAIL;
192  }
193 
194  return ERROR_OK;
195 }
196 
197 COMMAND_HANDLER(handle_rtt_stop_command)
198 {
199  if (CMD_ARGC != 1)
201 
202  remove_service("rtt", CMD_ARGV[0]);
203 
204  return ERROR_OK;
205 }
206 
208  {
209  .name = "start",
210  .handler = handle_rtt_start_command,
211  .mode = COMMAND_ANY,
212  .help = "Start a RTT server",
213  .usage = "<port> <channel> [message]"
214  },
215  {
216  .name = "stop",
217  .handler = handle_rtt_stop_command,
218  .mode = COMMAND_ANY,
219  .help = "Stop a RTT server",
220  .usage = "<port>"
221  },
223 };
224 
225 static const struct command_registration rtt_server_command_handlers[] = {
226  {
227  .name = "server",
228  .mode = COMMAND_ANY,
229  .help = "RTT server",
230  .usage = "",
232  },
234 };
235 
236 static const struct command_registration rtt_command_handlers[] = {
237  {
238  .name = "rtt",
239  .mode = COMMAND_ANY,
240  .help = "RTT",
241  .usage = "",
243  },
245 };
246 
248 {
250 }
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:442
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
static int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds)
Register one or more commands in the specified context, as children of parent (or top-level commends,...
Definition: command.h:274
@ COMMAND_ANY
Definition: command.h:42
uint8_t length
Definition: esp_usb_jtag.c:1
#define ERROR_FAIL
Definition: log.h:173
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:167
int rtt_register_sink(unsigned int channel_index, rtt_sink_read read, void *user_data)
Register an RTT sink.
Definition: rtt/rtt.c:206
int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read, void *user_data)
Unregister an RTT sink.
Definition: rtt/rtt.c:232
int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer, size_t *length)
Write to an RTT channel.
Definition: rtt/rtt.c:288
static int rtt_connection_closed(struct connection *connection)
Definition: rtt_server.c:90
static const struct command_registration rtt_command_handlers[]
Definition: rtt_server.c:236
static int rtt_new_connection(struct connection *connection)
Definition: rtt_server.c:61
static int rtt_input(struct connection *connection)
Definition: rtt_server.c:103
COMMAND_HANDLER(handle_rtt_start_command)
Definition: rtt_server.c:156
static int read_callback(unsigned int channel, const uint8_t *buffer, size_t length, void *user_data)
Definition: rtt_server.c:37
static const struct command_registration rtt_server_subcommand_handlers[]
Definition: rtt_server.c:207
int rtt_server_register_commands(struct command_context *ctx)
Definition: rtt_server.c:247
static const struct command_registration rtt_server_command_handlers[]
Definition: rtt_server.c:225
static const struct service_driver rtt_service_driver
Definition: rtt_server.c:147
int connection_write(struct connection *connection, const void *data, int len)
Definition: server.c:732
int connection_read(struct connection *connection, void *data, int len)
Definition: server.c:744
int remove_service(const char *name, const char *port)
Definition: server.c:355
int add_service(const struct service_driver *driver, const char *port, int max_connections, void *priv)
Definition: server.c:198
#define CONNECTION_LIMIT_UNLIMITED
Definition: server.h:34
#define ERROR_SERVER_REMOTE_CLOSED
Definition: server.h:119
const char * name
Definition: command.h:235
void * priv
Definition: server.h:43
struct service * service
Definition: server.h:41
bool input_pending
Definition: server.h:42
unsigned char buffer[64]
Definition: rtt_server.c:32
unsigned int offset
Definition: rtt_server.c:34
unsigned int length
Definition: rtt_server.c:33
unsigned int channel
Definition: rtt_server.c:27
char * hello_message
Definition: rtt_server.c:28
const char * name
the name of the server
Definition: server.h:49
Definition: server.h:67
void * priv
Definition: server.h:81
#define NULL
Definition: usb.h:16
uint8_t offset[4]
Definition: vdebug.c:9