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_READ 16
35 #define DEFAULT_TTY "/dev/ttyACM0"
44 uint8_t in_buf[CC_BUF];
46 uint8_t out_buf[CC_BUF];
48 struct cc_read read_buf[CC_NUM_READ];
55 cc_hex_nibble(uint8_t c)
57 if ('0' <= c && c <= '9')
59 if ('a' <= c && c <= 'f')
61 if ('A' <= c && c <= 'F')
67 * Take raw input bytes, parse them as hex
68 * and write them to the waiting buffer
71 cc_handle_in(struct cc_usb *cc)
79 while (read_pos < cc->read_count && in_pos < cc->in_count) {
81 * Skip to next hex character
83 while (in_pos < cc->in_count &&
84 cc_hex_nibble(cc->in_buf[in_pos]) == NOT_HEX)
87 * Make sure we have two characters left
89 if (cc->in_count - in_pos < 2)
94 h = cc_hex_nibble(cc->in_buf[in_pos]);
95 l = cc_hex_nibble(cc->in_buf[in_pos+1]);
96 if (h == NOT_HEX || l == NOT_HEX) {
97 fprintf(stderr, "hex read error\n");
104 *cc->read_buf[read_pos].buf++ = (h << 4) | l;
105 if (--cc->read_buf[read_pos].len <= 0)
109 /* Move remaining bytes to the start of the input buffer */
111 memmove(cc->in_buf, cc->in_buf + in_pos,
112 cc->in_count - in_pos);
113 cc->in_count -= in_pos;
116 /* Move pending reads to the start of the array */
118 memmove(cc->read_buf, cc->read_buf + read_pos,
119 (cc->read_count - read_pos) * sizeof (cc->read_buf[0]));
120 cc->read_count -= read_pos;
123 /* Once we're done reading, flush any pending input */
124 if (cc->read_count == 0)
129 cc_usb_dbg(int indent, uint8_t *bytes, int len)
137 for (i = 0; i < indent; i++)
138 ccdbg_debug(CC_DEBUG_BITBANG, " ");
143 ccdbg_debug(CC_DEBUG_BITBANG, "^M");
148 ccdbg_debug(CC_DEBUG_BITBANG, "%c", c);
154 * Flush pending writes, fill pending reads
157 cc_usb_sync(struct cc_usb *cc)
165 if (cc->read_count || cc->out_count)
170 if (cc->in_count < CC_BUF)
171 fds.events |= POLLIN;
173 fds.events |= POLLOUT;
174 ret = poll(&fds, 1, timeout);
181 if (fds.revents & POLLIN) {
182 ret = read(cc->fd, cc->in_buf + cc->in_count,
183 CC_BUF - cc->in_count);
185 cc_usb_dbg(24, cc->in_buf + cc->in_count, ret);
190 if (fds.revents & POLLOUT) {
191 ret = write(cc->fd, cc->out_buf,
194 cc_usb_dbg(0, cc->out_buf, ret);
197 cc->out_count - ret);
198 cc->out_count -= ret;
205 cc_usb_printf(struct cc_usb *cc, char *format, ...)
211 /* sprintf to a local buffer */
212 va_start(ap, format);
213 ret = vsnprintf(buf, sizeof(buf), format, ap);
215 if (ret > sizeof(buf)) {
216 fprintf(stderr, "printf overflow for format %s\n",
220 /* flush local buffer to the wire */
224 if (this_time > CC_BUF - cc->out_count)
225 this_time = CC_BUF - cc->out_count;
226 memcpy(cc->out_buf + cc->out_count, b, this_time);
227 cc->out_count += this_time;
229 while (cc->out_count >= CC_BUF)
235 cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len)
245 cc_usb_printf(cc, "P");
247 cc_usb_printf (cc, " %02x", (*bytes++) & 0xff);
248 cc_usb_printf(cc, "\n");
254 cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len)
256 struct cc_read *read_buf;
257 while (cc->read_count >= CC_NUM_READ)
259 read_buf = &cc->read_buf[cc->read_count++];
265 cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *buf, int len)
267 cc_queue_read(cc, buf, len);
268 cc_usb_printf(cc, "G %x\n", len);
273 cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len)
275 cc_usb_printf(cc, "O %x %x\n", len, addr);
277 cc_usb_printf(cc, "%02x", *bytes++);
282 cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len)
285 cc_queue_read(cc, bytes, len);
286 cc_usb_printf(cc, "I %x %x\n", len, addr);
288 for (i = 0; i < len; i++) {
291 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
292 ccdbg_debug(CC_DEBUG_MEMORY, "\t%04x", addr + i);
294 ccdbg_debug(CC_DEBUG_MEMORY, " %02x", bytes[i]);
296 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
301 cc_usb_debug_mode(struct cc_usb *cc)
304 cc_usb_printf(cc, "D\n");
309 cc_usb_reset(struct cc_usb *cc)
312 cc_usb_printf(cc, "R\n");
316 static struct termios save_termios;
323 struct termios termios;
325 tty = getenv("CCDBG_TTY");
328 cc = calloc (sizeof (struct cc_usb), 1);
331 cc->fd = open(tty, O_RDWR | O_NONBLOCK);
337 tcgetattr(cc->fd, &termios);
338 save_termios = termios;
340 tcsetattr(cc->fd, TCSAFLUSH, &termios);
341 cc_usb_printf(cc, "E 0\n");
349 cc_usb_close(struct cc_usb *cc)
351 tcsetattr(cc->fd, TCSAFLUSH, &save_termios);