2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
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.
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.
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.
19 #include <sys/types.h>
29 #include "ccdbg-debug.h"
33 #define CC_NUM_HEX_READ 64
35 * AltOS has different buffer sizes for in/out packets
37 #define CC_IN_BUF 65536
39 #define DEFAULT_TTY "/dev/ttyACM0"
48 uint8_t in_buf[CC_IN_BUF];
51 uint8_t out_buf[CC_OUT_BUF];
54 struct cc_hex_read hex_buf[CC_NUM_HEX_READ];
64 cc_hex_nibble(uint8_t c)
66 if ('0' <= c && c <= '9')
68 if ('a' <= c && c <= 'f')
70 if ('A' <= c && c <= 'F')
76 * Take raw input bytes, parse them as hex
77 * and write them to the waiting buffer
80 cc_handle_hex_read(struct cc_usb *cc)
86 while (hex_pos < cc->hex_count && cc->in_pos < cc->in_count) {
88 * Skip to next hex character
90 while (cc->in_pos < cc->in_count &&
91 cc_hex_nibble(cc->in_buf[cc->in_pos]) == NOT_HEX)
94 * Make sure we have two characters left
96 if (cc->in_count - cc->in_pos < 2)
101 h = cc_hex_nibble(cc->in_buf[cc->in_pos]);
102 l = cc_hex_nibble(cc->in_buf[cc->in_pos+1]);
103 if (h == NOT_HEX || l == NOT_HEX) {
104 fprintf(stderr, "hex read error\n");
111 *cc->hex_buf[hex_pos].buf++ = (h << 4) | l;
112 if (--cc->hex_buf[hex_pos].len <= 0)
116 /* Move pending hex reads to the start of the array */
118 memmove(cc->hex_buf, cc->hex_buf + hex_pos,
119 (cc->hex_count - hex_pos) * sizeof (cc->hex_buf[0]));
120 cc->hex_count -= hex_pos;
125 cc_usb_dbg(int indent, uint8_t *bytes, int len)
130 ccdbg_debug(CC_DEBUG_BITBANG, "<<<%d bytes>>>", len);
134 for (i = 0; i < indent; i++)
135 ccdbg_debug(CC_DEBUG_BITBANG, " ");
140 ccdbg_debug(CC_DEBUG_BITBANG, "\\r");
144 ccdbg_debug(CC_DEBUG_BITBANG, "\\n\n");
147 if (c < ' ' || c > '~')
148 ccdbg_debug(CC_DEBUG_BITBANG, "\\%02x", c);
150 ccdbg_debug(CC_DEBUG_BITBANG, "%c", c);
155 int cc_default_timeout = 5000;
158 * Flush pending writes, fill pending reads
162 _cc_usb_sync(struct cc_usb *cc, int wait_for_input, int write_timeout)
170 if (cc->hex_count || cc->out_count)
171 timeout = write_timeout;
172 else if (wait_for_input && cc->in_pos == cc->in_count)
173 timeout = wait_for_input;
177 /* Move remaining bytes to the start of the input buffer */
179 memmove(cc->in_buf, cc->in_buf + cc->in_pos,
180 cc->in_count - cc->in_pos);
181 cc->in_count -= cc->in_pos;
184 if (cc->in_count < CC_IN_BUF)
185 fds.events |= POLLIN;
187 fds.events |= POLLOUT;
188 ret = poll(&fds, 1, timeout);
198 if (fds.revents & POLLIN) {
199 ret = read(cc->fd, cc->in_buf + cc->in_count,
200 CC_IN_BUF - cc->in_count);
202 cc_usb_dbg(24, cc->in_buf + cc->in_count, ret);
205 cc_handle_hex_read(cc);
206 if (cc->show_input && cc->in_count) {
207 write(2, cc->in_buf, cc->in_count);
210 } else if (ret <= 0) {
215 if (fds.revents & POLLOUT) {
216 ret = write(cc->fd, cc->out_buf,
219 cc_usb_dbg(0, cc->out_buf, ret);
222 cc->out_count - ret);
223 cc->out_count -= ret;
232 cc_usb_sync(struct cc_usb *cc)
234 if (_cc_usb_sync(cc, 0, cc_default_timeout) < 0) {
235 fprintf(stderr, "USB link timeout\n");
241 cc_usb_printf(struct cc_usb *cc, char *format, ...)
247 /* sprintf to a local buffer */
248 va_start(ap, format);
249 ret = vsnprintf(buf, sizeof(buf), format, ap);
251 if (ret > sizeof(buf)) {
252 fprintf(stderr, "printf overflow for format %s\n",
256 /* flush local buffer to the wire */
260 if (this_time > CC_OUT_BUF - cc->out_count)
261 this_time = CC_OUT_BUF - cc->out_count;
262 memcpy(cc->out_buf + cc->out_count, b, this_time);
263 cc->out_count += this_time;
266 while (cc->out_count >= CC_OUT_BUF)
272 cc_usb_getchar_timeout(struct cc_usb *cc, int timeout)
274 while (cc->in_pos == cc->in_count) {
275 if (_cc_usb_sync(cc, timeout, cc_default_timeout) < 0) {
276 fprintf(stderr, "USB link timeout\n");
280 return cc->in_buf[cc->in_pos++];
284 cc_usb_getchar(struct cc_usb *cc)
286 return cc_usb_getchar_timeout(cc, cc_default_timeout);
290 cc_usb_getline(struct cc_usb *cc, char *line, int max)
294 while ((c = cc_usb_getchar(cc)) != '\n') {
310 cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len)
320 cc_usb_printf(cc, "P");
322 cc_usb_printf (cc, " %02x", (*bytes++) & 0xff);
323 cc_usb_printf(cc, "\n");
329 cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len)
331 struct cc_hex_read *hex_buf;
333 /* At the start of a command sequence, flush any pending input */
334 if (cc->hex_count == 0) {
338 while (cc->hex_count >= CC_NUM_HEX_READ)
340 hex_buf = &cc->hex_buf[cc->hex_count++];
346 cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *buf, int len)
348 cc_queue_read(cc, buf, len);
349 cc_usb_printf(cc, "G %x\n", len);
354 cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len)
356 cc_usb_printf(cc, "O %x %x\n", len, addr);
358 cc_usb_printf(cc, "%02x", *bytes++);
364 cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len)
367 cc_queue_read(cc, bytes, len);
368 cc_usb_printf(cc, "I %x %x\n", len, addr);
370 for (i = 0; i < len; i++) {
373 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
374 ccdbg_debug(CC_DEBUG_MEMORY, "\t%04x", addr + i);
376 ccdbg_debug(CC_DEBUG_MEMORY, " %02x", bytes[i]);
378 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
383 cc_usb_debug_mode(struct cc_usb *cc)
386 cc_usb_printf(cc, "D\n");
391 cc_usb_reset(struct cc_usb *cc)
394 cc_usb_printf(cc, "R\n");
399 cc_usb_open_remote(struct cc_usb *cc, int freq, char *call)
402 fprintf (stderr, "freq %dkHz\n", freq);
403 fprintf (stderr, "call %s\n", call);
404 cc_usb_printf(cc, "\nc F %d\nc c %s\np\nE 0\n", freq, call);
406 cc->in_count = cc->in_pos = 0;
407 _cc_usb_sync(cc, 100, cc_default_timeout);
408 } while (cc->in_count > 0);
414 cc_usb_close_remote(struct cc_usb *cc)
417 cc_usb_printf(cc, "~");
422 static struct termios save_termios;
427 cc_usb_open(char *tty)
430 struct termios termios;
435 cc = calloc (sizeof (struct cc_usb), 1);
440 cc->fd = open(tty, O_RDWR | O_NONBLOCK);
444 if (errno == EBUSY || errno == EPERM || errno == EACCES) {
445 fprintf(stderr, "open failed, pausing");
457 tcgetattr(cc->fd, &termios);
458 save_termios = termios;
460 cfsetospeed(&termios, B9600);
461 cfsetispeed(&termios, B9600);
462 tcsetattr(cc->fd, TCSAFLUSH, &termios);
463 cc_usb_printf(cc, "\nE 0\nm 0\n");
465 cc->in_count = cc->in_pos = 0;
466 _cc_usb_sync(cc, 100, cc_default_timeout);
467 } while (cc->in_count > 0);
472 cc_usb_close(struct cc_usb *cc)
474 cc_usb_close_remote(cc);
476 tcsetattr(cc->fd, TCSAFLUSH, &save_termios);
482 cc_usb_write(struct cc_usb *cc, void *buf, int c)
491 if (this_time > CC_OUT_BUF - cc->out_count)
492 this_time = CC_OUT_BUF - cc->out_count;
493 memcpy(cc->out_buf + cc->out_count, b, this_time);
494 cc->out_count += this_time;
497 while (cc->out_count >= CC_OUT_BUF) {
498 _cc_usb_sync(cc, 0, -1);