Audit and eliminate redundant #include directives in other target files.
[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 "target_request.h"
31 #include "binarybuffer.h"
32 #include "trace.h"
33 #include "log.h"
34
35
36 static command_t *target_request_cmd = NULL;
37 static int charmsg_mode = 0;
38
39 static int target_asciimsg(target_t *target, u32 length)
40 {
41         char *msg = malloc(CEIL(length + 1, 4) * 4);
42         debug_msg_receiver_t *c = target->dbgmsg;
43         
44         target->type->target_request_data(target, CEIL(length, 4), (u8*)msg);
45         msg[length] = 0;
46         
47         LOG_DEBUG("%s", msg);
48         
49         while (c)
50         {
51                 command_print(c->cmd_ctx, "%s", msg);
52                 c = c->next;
53         }
54         
55         return ERROR_OK;
56 }
57
58 static int target_charmsg(target_t *target, u8 msg)
59 {
60         LOG_USER_N("%c", msg);
61         
62         return ERROR_OK;
63 }
64
65 static int target_hexmsg(target_t *target, int size, u32 length)
66 {
67         u8 *data = malloc(CEIL(length * size, 4) * 4);
68         char line[128];
69         int line_len;
70         debug_msg_receiver_t *c = target->dbgmsg;
71         u32 i;
72         
73         LOG_DEBUG("size: %i, length: %i", size, length);
74
75         target->type->target_request_data(target, CEIL(length * size, 4), (u8*)data);
76
77         line_len = 0;
78         for (i = 0; i < length; i++)
79         {
80                 switch (size)
81                 {
82                         case 4:
83                                 line_len += snprintf(line + line_len, 128 - line_len, "%8.8x ", le_to_h_u32(data + (4*i)));
84                                 break;
85                         case 2:
86                                 line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
87                                 break;
88                         case 1:
89                                 line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
90                                 break;
91                 }
92                 
93                 if ((i%8 == 7) || (i == length - 1))
94                 {
95                         LOG_DEBUG("%s", line);
96                         
97                         while (c)
98                         {
99                                 command_print(c->cmd_ctx, "%s", line);
100                                 c = c->next;
101                         }
102                         c = target->dbgmsg;
103                         line_len = 0;
104                 }
105         }
106         
107         free(data);
108
109         return ERROR_OK;
110 }
111
112 /* handle requests from the target received by a target specific
113  * side-band channel (e.g. ARM7/9 DCC)
114  */
115 int target_request(target_t *target, u32 request)
116 {
117         target_req_cmd_t target_req_cmd = request & 0xff;
118
119         if ( charmsg_mode ) {
120                 target_charmsg(target, target_req_cmd );
121                 return ERROR_OK;
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 static 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 static 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 static 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") || !strcmp(args[0], "charmsg"))
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                         charmsg_mode = !strcmp(args[0], "charmsg");
280                 }
281                 else if (!strcmp(args[0], "disable"))
282                 {
283                         /* no need to delete a receiver if none is registered */
284                         if (receiving)
285                         {
286                                 receiving = 0;
287                                 delete_debug_msg_receiver(cmd_ctx, target);
288                         }
289                 }
290                 else
291                 {
292                         command_print(cmd_ctx, "usage: target_request debugmsgs ['enable'|'disable'|'charmsg']");
293                 }
294         }
295         
296         command_print(cmd_ctx, "receiving debug messages from current target %s",
297                       (receiving) ? (charmsg_mode?"charmsg":"enabled") : "disabled" );
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 }