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