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