Summary: passing of variable argument list reduced, strings sent to logging are now...
[fw/openocd] / src / target / target_request.c
1 /***************************************************************************
2  *   Copyright (C) 2007 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.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, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25 #include "log.h"
26 #include "target.h"
27 #include "target_request.h"
28 #include "binarybuffer.h"
29 #include "command.h"
30 #include "trace.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 command_t *target_request_cmd = NULL;
36
37 int target_asciimsg(target_t *target, u32 length)
38 {
39         char *msg = malloc(CEIL(length + 1, 4) * 4);
40         debug_msg_receiver_t *c = target->dbgmsg;
41         
42         target->type->target_request_data(target, CEIL(length, 4), (u8*)msg);
43         msg[length] = 0;
44         
45         DEBUG("%s", msg);
46         
47         while (c)
48         {
49                 command_print(c->cmd_ctx, "%s", msg);
50                 c = c->next;
51         }
52         
53         return ERROR_OK;
54 }
55
56 int target_charmsg(target_t *target, u8 msg)
57 {
58         USER_N("%c", msg);
59         
60         return ERROR_OK;
61 }
62
63 int target_hexmsg(target_t *target, int size, u32 length)
64 {
65         u8 *data = malloc(CEIL(length * size, 4) * 4);
66         char line[128];
67         int line_len;
68         debug_msg_receiver_t *c = target->dbgmsg;
69         int i;
70         
71         DEBUG("size: %i, length: %i", size, length);
72
73         target->type->target_request_data(target, CEIL(length * size, 4), (u8*)data);
74
75         line_len = 0;
76         for (i = 0; i < length; i++)
77         {
78                 switch (size)
79                 {
80                         case 4:
81                                 line_len += snprintf(line + line_len, 128 - line_len, "%8.8x ", le_to_h_u32(data + (4*i)));
82                                 break;
83                         case 2:
84                                 line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
85                                 break;
86                         case 1:
87                                 line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
88                                 break;
89                 }
90                 
91                 if ((i%8 == 7) || (i == length - 1))
92                 {
93                         DEBUG("%s", line);
94                         
95                         while (c)
96                         {
97                                 command_print(c->cmd_ctx, "%s", line);
98                                 c = c->next;
99                         }
100                         c = target->dbgmsg;
101                         line_len = 0;
102                 }
103         }
104         
105         free(data);
106
107         return ERROR_OK;
108 }
109
110 /* handle requests from the target received by a target specific
111  * side-band channel (e.g. ARM7/9 DCC)
112  */
113 int target_request(target_t *target, u32 request)
114 {
115         target_req_cmd_t target_req_cmd = request & 0xff;
116         
117         switch (target_req_cmd)
118         {
119                 case TARGET_REQ_TRACEMSG:
120                         trace_point(target, (request & 0xffffff00) >> 8);
121                         break;
122                 case TARGET_REQ_DEBUGMSG:
123                         if (((request & 0xff00) >> 8) == 0)
124                         {
125                                 target_asciimsg(target, (request & 0xffff0000) >> 16);
126                         }
127                         else
128                         {
129                                 target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
130                         }
131                         break;
132                 case TARGET_REQ_DEBUGCHAR:
133                         target_charmsg(target, (request & 0x00ff0000) >> 16);
134                         break;
135 /*              case TARGET_REQ_SEMIHOSTING:
136  *                      break;
137  */
138                 default:
139                         ERROR("unknown target request: %2.2x", target_req_cmd);
140                         break;
141         }
142         
143         return ERROR_OK;
144 }
145
146 int add_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
147 {
148         debug_msg_receiver_t **p = &target->dbgmsg;
149         
150         if (target == NULL)
151                 return ERROR_INVALID_ARGUMENTS;
152
153         /* see if there's already a list */
154         if (*p)
155         {
156                 /* find end of linked list */
157                 p = &target->dbgmsg;
158                 while ((*p)->next)
159                         p = &((*p)->next);
160                 p = &((*p)->next);
161         }
162
163         /* add new debug message receiver */
164         (*p) = malloc(sizeof(debug_msg_receiver_t));
165         (*p)->cmd_ctx = cmd_ctx;
166         (*p)->next = NULL;
167         
168         /* enable callback */
169         target->dbg_msg_enabled = 1;
170         
171         return ERROR_OK;
172 }
173
174 debug_msg_receiver_t* find_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
175 {
176         int all_targets = 0;
177         debug_msg_receiver_t **p = &target->dbgmsg;
178         
179         /* if no target has been specified search all of them */
180         if (target == NULL)
181         {
182                 /* if no targets haven been specified */
183                 if (targets == NULL)
184                         return NULL;
185
186                 target = targets;
187                 all_targets = 1;
188         }
189         
190         do
191         {
192                 while (*p)
193                 {
194                         if ((*p)->cmd_ctx == cmd_ctx)
195                         {
196                                 return *p;
197                         }
198                         p = &((*p)->next);
199                 }
200                 
201                 target = target->next;
202         } while (target && all_targets);
203         
204         return NULL;
205 }
206
207 int delete_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
208 {
209         debug_msg_receiver_t **p;
210         debug_msg_receiver_t *c;
211         int all_targets = 0;
212         
213         /* if no target has been specified search all of them */
214         if (target == NULL)
215         {
216                 /* if no targets haven been specified */
217                 if (targets == NULL)
218                         return ERROR_OK;
219                 
220                 target = targets;
221                 all_targets = 1;
222         }
223
224         do
225         {
226                 p = &target->dbgmsg;
227                 c = *p;
228                 while (c)
229                 {
230                         debug_msg_receiver_t *next = c->next;
231                         if (c->cmd_ctx == cmd_ctx)
232                         {
233                                 *p = next;
234                                 free(c);
235                                 if (*p == NULL)
236                                 {
237                                         /* disable callback */
238                                         target->dbg_msg_enabled = 0;
239                                 }
240                                 return ERROR_OK;
241                         }
242                         else
243                                 p = &(c->next);
244                         c = next;
245                 }
246         
247                 target = target->next;
248         } while (target && all_targets);
249         
250         return ERROR_OK;
251 }
252
253 int handle_target_request_debugmsgs_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
254 {
255         target_t *target = get_current_target(cmd_ctx);
256
257         int receiving = 0;
258         
259         /* see if reciever is already registered */
260         if (find_debug_msg_receiver(cmd_ctx, target) != NULL)
261                 receiving = 1;
262
263         if (argc > 0)
264         {
265                 if (!strcmp(args[0], "enable"))
266                 {
267                         /* don't register if this command context is already receiving */
268                         if (!receiving)
269                         {
270                                 receiving = 1;
271                                 add_debug_msg_receiver(cmd_ctx, target);
272                         }
273                 }
274                 else if (!strcmp(args[0], "disable"))
275                 {
276                         /* no need to delete a receiver if none is registered */
277                         if (receiving)
278                         {
279                                 receiving = 0;
280                                 delete_debug_msg_receiver(cmd_ctx, target);
281                         }
282                 }
283                 else
284                 {
285                         command_print(cmd_ctx, "usage: target_request debugmsgs ['enable'|'disable']");
286                 }
287         }
288         
289         command_print(cmd_ctx, "receiving debug messages from current target %s",
290                         (receiving) ? "enabled" : "disabled");
291         
292         return ERROR_OK;
293 }
294
295 int target_request_register_commands(struct command_context_s *cmd_ctx)
296 {
297         target_request_cmd =
298                 register_command(cmd_ctx, NULL, "target_request", NULL, COMMAND_ANY, "target_request commands");
299         
300         register_command(cmd_ctx, target_request_cmd, "debugmsgs", handle_target_request_debugmsgs_command,
301                 COMMAND_EXEC, "enable/disable reception of debug messgages from target");
302
303         return ERROR_OK;
304 }