Separate transports from drivers.

The transport/ subdirectory now contains implementations of the
transport_t interface, which has been expanded to include flush and
set_modem operations.
This commit is contained in:
Daniel Beer 2012-09-10 14:22:00 +12:00
parent c66e885899
commit d844adf828
13 changed files with 197 additions and 55 deletions

View File

@ -70,7 +70,7 @@ else
endif endif
INCLUDES = -I. -Isimio -Iformats -Idrivers -Iutil -Iui INCLUDES = -I. -Isimio -Iformats -Itransport -Idrivers -Iutil -Iui
GCC_CFLAGS = -O1 -Wall -Wno-char-subscripts -ggdb GCC_CFLAGS = -O1 -Wall -Wno-char-subscripts -ggdb
CONFIG_CFLAGS = -DLIB_DIR=\"$(LIBDIR)\" CONFIG_CFLAGS = -DLIB_DIR=\"$(LIBDIR)\"
@ -114,6 +114,11 @@ OBJ=\
util/gdb_proto.o \ util/gdb_proto.o \
util/dynload.o \ util/dynload.o \
util/demangle.o \ util/demangle.o \
transport/olimex.o \
transport/olimex_iso.o \
transport/rf2500.o \
transport/ti3410.o \
transport/uif.o \
drivers/device.o \ drivers/device.o \
drivers/bsl.o \ drivers/bsl.o \
drivers/fet.o \ drivers/fet.o \
@ -121,13 +126,8 @@ OBJ=\
drivers/fet_db.o \ drivers/fet_db.o \
drivers/flash_bsl.o \ drivers/flash_bsl.o \
drivers/gdbc.o \ drivers/gdbc.o \
drivers/olimex.o \
drivers/rf2500.o \
drivers/sim.o \ drivers/sim.o \
drivers/uif.o \
drivers/ti3410.o \
drivers/tilib.o \ drivers/tilib.o \
drivers/olimex_iso.o \
drivers/goodfet.o \ drivers/goodfet.o \
formats/binfile.o \ formats/binfile.o \
formats/coff.o \ formats/coff.o \

View File

@ -231,7 +231,8 @@ static int send_rf2500_data(struct fet_device *dev,
pbuf[2] = offset >> 8; pbuf[2] = offset >> 8;
pbuf[3] = plen; pbuf[3] = plen;
memcpy(pbuf + 4, data, plen); memcpy(pbuf + 4, data, plen);
if (dev->transport->send(dev->transport, pbuf, plen + 4) < 0) if (dev->transport->ops->send(dev->transport,
pbuf, plen + 4) < 0)
return -1; return -1;
data += plen; data += plen;
@ -360,10 +361,10 @@ static int recv_packet(struct fet_device *dev)
if (dev->fet_len >= plen + pkt_extra) if (dev->fet_len >= plen + pkt_extra)
return parse_packet(dev, plen); return parse_packet(dev, plen);
len = dev->transport->recv(dev->transport, len = dev->transport->ops->recv(dev->transport,
dev->fet_buf + dev->fet_len, dev->fet_buf + dev->fet_len,
sizeof(dev->fet_buf) - sizeof(dev->fet_buf) -
dev->fet_len); dev->fet_len);
if (len < 0) if (len < 0)
return -1; return -1;
dev->fet_len += len; dev->fet_len += len;
@ -449,7 +450,7 @@ static int send_command(struct fet_device *dev, int command_code,
assert (i < sizeof(buf)); assert (i < sizeof(buf));
return dev->transport->send(dev->transport, buf, i); return dev->transport->ops->send(dev->transport, buf, i);
} }
static int xfer(struct fet_device *dev, static int xfer(struct fet_device *dev,
@ -776,7 +777,7 @@ static void fet_destroy(device_t dev_base)
if (xfer(dev, C_CLOSE, NULL, 0, 1, 0) < 0) if (xfer(dev, C_CLOSE, NULL, 0, 1, 0) < 0)
printc_err("fet: close command failed\n"); printc_err("fet: close command failed\n");
dev->transport->destroy(dev->transport); dev->transport->ops->destroy(dev->transport);
free(dev); free(dev);
} }
@ -995,9 +996,11 @@ int try_open(struct fet_device *dev, const struct device_args *args,
if (dev->flags & FET_PROTO_NOLEAD_SEND) { if (dev->flags & FET_PROTO_NOLEAD_SEND) {
printc("Resetting Olimex command processor...\n"); printc("Resetting Olimex command processor...\n");
transport->send(dev->transport, (const uint8_t *)"\x7e", 1); transport->ops->send(dev->transport,
(const uint8_t *)"\x7e", 1);
delay_ms(5); delay_ms(5);
transport->send(dev->transport, (const uint8_t *)"\x7e", 1); transport->ops->send(dev->transport,
(const uint8_t *)"\x7e", 1);
delay_ms(5); delay_ms(5);
} }
@ -1073,7 +1076,7 @@ static device_t fet_open(const struct device_args *args,
return (device_t)dev; return (device_t)dev;
fail: fail:
transport->destroy(transport); transport->ops->destroy(transport);
free(dev); free(dev);
return NULL; return NULL;
} }

View File

@ -1,5 +1,5 @@
/* MSPDebug - debugging tool for the eZ430 /* MSPDebug - debugging tool for the eZ430
* Copyright (C) 2009-2011 Daniel Beer * Copyright (C) 2009-2012 Daniel Beer
* Copyright (C) 2010 Peter Jansen * Copyright (C) 2010 Peter Jansen
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -260,20 +260,44 @@ static void usbtr_destroy(transport_t tr_base)
free(tr); free(tr);
} }
static int usbtr_flush(transport_t tr_base)
{
struct olimex_transport *tr = (struct olimex_transport *)tr_base;
char buf[64];
/* Flush out lingering data */
while (usb_bulk_read(tr->handle, tr->in_ep,
buf, sizeof(buf),
100) > 0);
return 0;
}
static int usbtr_set_modem(transport_t tr_base, transport_modem_t state)
{
printc_err("olimex: unsupported operation: set_modem\n");
return -1;
}
static const struct transport_class olimex_transport = {
.destroy = usbtr_destroy,
.send = usbtr_send,
.recv = usbtr_recv,
.flush = usbtr_flush,
.set_modem = usbtr_set_modem
};
transport_t olimex_open(const char *devpath, const char *requested_serial) transport_t olimex_open(const char *devpath, const char *requested_serial)
{ {
struct olimex_transport *tr = malloc(sizeof(*tr)); struct olimex_transport *tr = malloc(sizeof(*tr));
struct usb_device *dev; struct usb_device *dev;
char buf[64];
if (!tr) { if (!tr) {
pr_error(__FILE__": can't allocate memory"); pr_error(__FILE__": can't allocate memory");
return NULL; return NULL;
} }
tr->base.destroy = usbtr_destroy; tr->base.ops = &olimex_transport;
tr->base.send = usbtr_send;
tr->base.recv = usbtr_recv;
usb_init(); usb_init();
usb_find_busses(); usb_find_busses();
@ -299,10 +323,7 @@ transport_t olimex_open(const char *devpath, const char *requested_serial)
return NULL; return NULL;
} }
/* Flush out lingering data */ usbtr_flush(&tr->base);
while (usb_bulk_read(tr->handle, tr->in_ep,
buf, sizeof(buf),
100) > 0);
return (transport_t)tr; return (transport_t)tr;
} }

View File

@ -226,6 +226,25 @@ static int tr_send(transport_t tr_base, const uint8_t *databuf, int len)
return 0; return 0;
} }
static int tr_flush(transport_t tr_base)
{
return 0;
}
static int tr_set_modem(transport_t tr_base, transport_modem_t state)
{
printc_err("olimex_iso: unsupported operation: set_modem\n");
return -1;
}
static const struct transport_class olimex_iso_transport = {
.destroy = tr_destroy,
.send = tr_send,
.recv = tr_recv,
.flush = tr_flush,
.set_modem = tr_set_modem
};
transport_t olimex_iso_open(const char *devpath, transport_t olimex_iso_open(const char *devpath,
const char *requested_serial) const char *requested_serial)
{ {
@ -237,9 +256,7 @@ transport_t olimex_iso_open(const char *devpath,
return NULL; return NULL;
} }
tr->base.destroy = tr_destroy; tr->base.ops = &olimex_iso_transport;
tr->base.send = tr_send;
tr->base.recv = tr_recv;
usb_init(); usb_init();
usb_find_busses(); usb_find_busses();

View File

@ -1,5 +1,5 @@
/* MSPDebug - debugging tool for the eZ430 /* MSPDebug - debugging tool for the eZ430
* Copyright (C) 2009, 2010 Daniel Beer * Copyright (C) 2009-2012 Daniel Beer
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -188,20 +188,50 @@ static void usbtr_destroy(transport_t tr_base)
free(tr); free(tr);
} }
static int usbtr_flush(transport_t tr_base)
{
#ifndef __APPLE__
struct rf2500_transport *tr = (struct rf2500_transport *)tr_base;
char buf[64];
/* Flush out lingering data.
*
* The timeout apparently doesn't work on OS/X, and this loop
* just hangs once the endpoint buffer empties.
*/
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) > 0);
#endif
return 0;
}
static int usbtr_set_modem(transport_t tr_base, transport_modem_t state)
{
printc_err("rf2500: unsupported operation: set_modem\n");
return -1;
}
static const struct transport_class rf2500_transport = {
.destroy = usbtr_destroy,
.send = usbtr_send,
.recv = usbtr_recv,
.flush = usbtr_flush,
.set_modem = usbtr_set_modem
};
transport_t rf2500_open(const char *devpath, const char *requested_serial) transport_t rf2500_open(const char *devpath, const char *requested_serial)
{ {
struct rf2500_transport *tr = malloc(sizeof(*tr)); struct rf2500_transport *tr = malloc(sizeof(*tr));
struct usb_device *dev; struct usb_device *dev;
char buf[64];
if (!tr) { if (!tr) {
pr_error("rf2500: can't allocate memory"); pr_error("rf2500: can't allocate memory");
return NULL; return NULL;
} }
tr->base.destroy = usbtr_destroy; tr->base.ops = &rf2500_transport;
tr->base.send = usbtr_send;
tr->base.recv = usbtr_recv;
usb_init(); usb_init();
usb_find_busses(); usb_find_busses();
@ -223,16 +253,7 @@ transport_t rf2500_open(const char *devpath, const char *requested_serial)
return NULL; return NULL;
} }
/* Flush out lingering data. usbtr_flush(&tr->base);
*
* The timeout apparently doesn't work on OS/X, and this loop
* just hangs once the endpoint buffer empties.
*/
#ifndef __APPLE__
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) > 0);
#endif
return (transport_t)tr; return (transport_t)tr;
} }

View File

@ -535,6 +535,25 @@ static int download_firmware(struct usb_device *dev)
return 0; return 0;
} }
static int ti3410_flush(transport_t tr_base)
{
return 0;
}
static int ti3410_set_modem(transport_t tr_base, transport_modem_t state)
{
printc_err("ti3410: unsupported operation: set_modem\n");
return -1;
}
static const struct transport_class ti3410_transport = {
.destroy = ti3410_destroy,
.send = ti3410_send,
.recv = ti3410_recv,
.flush = ti3410_flush,
.set_modem = ti3410_set_modem
};
transport_t ti3410_open(const char *devpath, const char *requested_serial) transport_t ti3410_open(const char *devpath, const char *requested_serial)
{ {
struct ti3410_transport *tr = malloc(sizeof(*tr)); struct ti3410_transport *tr = malloc(sizeof(*tr));
@ -545,9 +564,7 @@ transport_t ti3410_open(const char *devpath, const char *requested_serial)
return NULL; return NULL;
} }
tr->base.destroy = ti3410_destroy; tr->base.ops = &ti3410_transport;
tr->base.send = ti3410_send;
tr->base.recv = ti3410_recv;
usb_init(); usb_init();
usb_find_busses(); usb_find_busses();

View File

@ -1,5 +1,5 @@
/* MSPDebug - debugging tool for MSP430 MCUs /* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 Daniel Beer * Copyright (C) 2009-2012 Daniel Beer
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,18 +21,44 @@
#include <stdint.h> #include <stdint.h>
/* This structure is used to provide an interface to a lower-level /* This structure is used to provide a consistent interface to a
* transport. The transport mechanism is viewed as a stream by the FET * lower-level serial-port type device.
* controller, which handles packet encapsulation, checksums and other
* high-level functions.
*/ */
struct transport; struct transport;
typedef struct transport *transport_t; typedef struct transport *transport_t;
struct transport { typedef enum {
TRANSPORT_MODEM_DTR = 0x01,
TRANSPORT_MODEM_RTS = 0x02
} transport_modem_t;
struct transport_class {
/* Close the port and free resources */
void (*destroy)(transport_t tr); void (*destroy)(transport_t tr);
/* Send a block of data. Returns 0 on success, or -1 if an error
* occurs.
*/
int (*send)(transport_t tr, const uint8_t *data, int len); int (*send)(transport_t tr, const uint8_t *data, int len);
/* Receive a block of data, up to the maximum size. Returns the
* number of bytes received on success (which must be non-zero),
* or -1 if an error occurs. Read timeouts are treated as
* errors.
*/
int (*recv)(transport_t tr, uint8_t *data, int max_len); int (*recv)(transport_t tr, uint8_t *data, int max_len);
/* Flush any lingering data in either direction. */
int (*flush)(transport_t tr);
/* Set modem control lines. Returns 0 on success or -1 if an
* error occurs.
*/
int (*set_modem)(transport_t tr, transport_modem_t state);
};
struct transport {
const struct transport_class *ops;
}; };
#endif #endif

View File

@ -75,6 +75,45 @@ static void serial_destroy(transport_t tr_base)
free(tr); free(tr);
} }
static int serial_flush(transport_t tr_base)
{
struct uif_transport *tr = (struct uif_transport *)tr_base;
if (sport_flush(tr->serial_fd) < 0) {
pr_error("uif: flush failed");
return -1;
}
return 0;
}
static int serial_set_modem(transport_t tr_base, transport_modem_t state)
{
struct uif_transport *tr = (struct uif_transport *)tr_base;
int bits = 0;
if (state & TRANSPORT_MODEM_DTR)
bits |= SPORT_MC_DTR;
if (state & TRANSPORT_MODEM_RTS)
bits |= SPORT_MC_RTS;
if (sport_set_modem(tr->serial_fd, bits) < 0) {
pr_error("uif: failed to set modem control lines\n");
return -1;
}
return 0;
}
static const struct transport_class uif_transport = {
.destroy = serial_destroy,
.send = serial_send,
.recv = serial_recv,
.flush = serial_flush,
.set_modem = serial_set_modem
};
transport_t uif_open(const char *device, uif_type_t type) transport_t uif_open(const char *device, uif_type_t type)
{ {
struct uif_transport *tr = malloc(sizeof(*tr)); struct uif_transport *tr = malloc(sizeof(*tr));
@ -84,9 +123,7 @@ transport_t uif_open(const char *device, uif_type_t type)
return NULL; return NULL;
} }
tr->base.send = serial_send; tr->base.ops = &uif_transport;
tr->base.recv = serial_recv;
tr->base.destroy = serial_destroy;
switch (type) { switch (type) {
case UIF_TYPE_FET: case UIF_TYPE_FET: