ao-tools: Add ao-flash-stm and ao-flash-lpc scripts
[fw/altos] / ao-tools / ao-dbg / ao-dbg-main.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ao-dbg.h"
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <signal.h>
25 #include <stdarg.h>
26 #include <poll.h>
27 #include <getopt.h>
28
29 static int s51_port = 0;
30 static char *cpu = "8051";
31 static double freq = 11059200;
32 char *s51_prompt = "> ";
33 struct ccdbg *s51_dbg;
34 int s51_interrupted = 0;
35 int s51_monitor = 0;
36 char *s51_tty = NULL;
37 char *s51_device = NULL;
38
39 static FILE *s51_input;
40 static FILE *s51_output;
41
42 static void
43 usage(void)
44 {
45         fprintf(stderr, "You're doing it wrong.\n");
46         exit(1);
47 }
48
49 void s51_sigint()
50 {
51         s51_interrupted = 1;
52 }
53
54 static const struct option options[] = {
55         { .name = "tty", .has_arg = 1, .val = 'T' },
56         { .name = "device", .has_arg = 1, .val = 'D' },
57         { 0, 0, 0, 0 },
58 };
59
60 int
61 main(int argc, char **argv)
62 {
63         int flags, opt;
64         char *endptr;
65         struct sigvec vec, ovec;
66
67         while ((opt = getopt_long(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:T:", options, NULL)) != -1) {
68                 switch (opt) {
69                 case 't':
70                         cpu = optarg;
71                         break;
72                 case 'X':
73                         freq = strtod(optarg, &endptr);
74                         if (endptr == optarg)
75                                 usage();
76                         if (endptr[0] != '\0') {
77                                 if (!strcmp(endptr, "k"))
78                                         freq *= 1000;
79                                 else if (!strcmp(endptr, "M") )
80                                         freq *= 1000000;
81                                 else
82                                         usage ();
83                         }
84                         break;
85                 case 'c':
86                         break;
87                 case 'r':
88                 case 'Z':
89                         s51_port = strtol(optarg, &endptr, 0);
90                         if (endptr == optarg || strlen(endptr) != 0)
91                                 usage();
92                         break;
93                 case 's':
94                         break;
95                 case 'S':
96                         break;
97                 case 'p':
98                         s51_prompt = optarg;
99                         break;
100                 case 'P':
101                         s51_prompt = NULL;
102                         break;
103                 case 'V':
104                         break;
105                 case 'v':
106                         break;
107                 case 'H':
108                         exit (0);
109                         break;
110                 case 'h':
111                         usage ();
112                         break;
113                 case 'm':
114                         s51_monitor = 1;
115                         break;
116                 case 'T':
117                         s51_tty = optarg;
118                         break;
119                 case 'D':
120                         s51_device = optarg;
121                         break;
122                 }
123         }
124         if (s51_port) {
125                 int l, r, one = 1;
126                 int s;
127                 struct sockaddr_in in;
128
129                 l = socket(AF_INET, SOCK_STREAM, 0);
130                 if (l < 0) {
131                         perror ("socket");
132                         exit(1);
133                 }
134                 r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int));
135                 if (r) {
136                         perror("setsockopt");
137                         exit(1);
138                 }
139                 in.sin_family = AF_INET;
140                 in.sin_port = htons(s51_port);
141                 in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
142                 r = bind(l, (struct sockaddr *) &in, sizeof (in));
143                 if (r) {
144                         perror("bind");
145                         exit(1);
146                 }
147                 r = listen(l, 5);
148                 if (r) {
149                         perror("listen");
150                         exit(1);
151                 }
152                 for (;;) {
153                         struct sockaddr_in client_addr;
154                         socklen_t client_len = sizeof (struct sockaddr_in);
155
156                         s = accept(l, (struct sockaddr *)
157                                    &client_addr, &client_len);
158                         if (s < 0) {
159                                 perror("accept");
160                                 exit(1);
161                         }
162                         s51_input = fdopen(s, "r");
163                         s51_output = fdopen(s, "w");
164                         if (!s51_input || !s51_output) {
165                                 perror("fdopen");
166                                 exit(1);
167                         }
168                         vec.sv_handler = SIG_IGN;
169                         vec.sv_mask = 0;
170                         vec.sv_flags = 0;
171                         sigvec(SIGINT, &vec, &ovec);
172                         command_read();
173                         sigvec(SIGINT, &ovec, NULL);
174                         fclose(s51_input);
175                         fclose(s51_output);
176                 }
177         } else {
178                 s51_input = stdin;
179                 s51_output = stdout;
180                 vec.sv_handler = s51_sigint;
181                 vec.sv_mask = 0;
182                 vec.sv_flags = 0;
183                 sigvec(SIGINT, &vec, &ovec);
184                 command_read();
185         }
186         exit(0);
187 }
188
189 void
190 s51_printf(char *format, ...)
191 {
192         va_list ap;
193
194         va_start(ap, format);
195         vfprintf(s51_output, format, ap);
196         if (s51_monitor)
197                 vfprintf(stdout, format, ap);
198         va_end(ap);
199 }
200
201 void
202 s51_putc(int c)
203 {
204         putc(c, s51_output);
205 }
206
207 #include <readline/readline.h>
208 #include <readline/history.h>
209
210 int
211 s51_read_line(char *line, int len)
212 {
213         int ret;
214         if (s51_output == stdout && s51_input == stdin && s51_prompt) {
215                 char *r;
216
217                 r = readline(s51_prompt);
218                 if (r == NULL)
219                         return 0;
220                 strncpy (line, r, len);
221                 line[len-1] = '\0';
222                 add_history(r);
223                 return 1;
224         } else {
225                 if (s51_prompt)
226                         s51_printf("%s", s51_prompt);
227                 else
228                         s51_putc('\0');
229                 fflush(s51_output);
230                 ret = fgets(line, len, s51_input) != NULL;
231                 if (s51_monitor)
232                         printf("> %s", line);
233                 fflush(stdout);
234         }
235         return ret;
236 }
237
238 int
239 s51_check_input(void)
240 {
241         struct pollfd   input;
242         int r;
243         int c;
244
245         input.fd = fileno(s51_input);
246         input.events = POLLIN;
247         r = poll(&input, 1, 0);
248         if (r > 0) {
249                 char line[256];
250                 (void) s51_read_line(line, sizeof (line));
251                 return 1;
252         }
253         return 0;
254 }