Replace "olimex_iso" transport with generic "ftdi".

Constructor now takes arguments for vendor/product IDs and baud rate.
This commit is contained in:
Daniel Beer 2012-09-13 14:53:30 +12:00
parent 1392cea7e1
commit 837e1d8e00
4 changed files with 91 additions and 77 deletions

View File

@ -116,7 +116,7 @@ OBJ=\
util/demangle.o \ util/demangle.o \
transport/cp210x.o \ transport/cp210x.o \
transport/cdc_acm.o \ transport/cdc_acm.o \
transport/olimex_iso.o \ transport/ftdi.o \
transport/rf2500.o \ transport/rf2500.o \
transport/ti3410.o \ transport/ti3410.o \
transport/comport.o \ transport/comport.o \

View File

@ -35,7 +35,7 @@
#include "opdb.h" #include "opdb.h"
#include "comport.h" #include "comport.h"
#include "olimex_iso.h" #include "ftdi.h"
#include "rf2500.h" #include "rf2500.h"
#include "ti3410.h" #include "ti3410.h"
#include "cp210x.h" #include "cp210x.h"
@ -1249,7 +1249,8 @@ static device_t fet_open_olimex_iso(const struct device_args *args)
if (args->flags & DEVICE_FLAG_TTY) if (args->flags & DEVICE_FLAG_TTY)
trans = comport_open(args->path, 200000); trans = comport_open(args->path, 200000);
else else
trans = olimex_iso_open(args->path, args->requested_serial); trans = ftdi_open(args->path, args->requested_serial,
0x15ba, 0x0008, 200000);
if (!trans) if (!trans)
return NULL; return NULL;

View File

@ -20,18 +20,16 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "olimex_iso.h" #include "ftdi.h"
#include "util.h" #include "util.h"
#include "usbutil.h" #include "usbutil.h"
#include "output.h" #include "output.h"
struct iso_transport { struct ftdi_transport {
struct transport base; struct transport base;
struct usb_dev_handle *handle; struct usb_dev_handle *handle;
}; };
#define USB_VENDOR 0x15ba
#define USB_PRODUCT 0x0008
#define USB_INTERFACE 0 #define USB_INTERFACE 0
#define USB_CONFIG 1 #define USB_CONFIG 1
@ -62,61 +60,61 @@ struct iso_transport {
#define FTDI_PACKET_SIZE 64 #define FTDI_PACKET_SIZE 64
struct config_rec { #define FTDI_CLOCK 3000000
const char *desc;
int request;
int value;
};
static const struct config_rec config[] = { #define FTDI_DTR 0x0001
{"reset FTDI", #define FTDI_RTS 0x0002
FTDI_SIO_RESET, FTDI_SIO_RESET_SIO}, #define FTDI_WRITE_DTR 0x0100
{"set data characteristics", #define FTDI_WRITE_RTS 0x0200
FTDI_SIO_SET_DATA, 8}, /* 8,N,1 */
{"disable flow control",
FTDI_SIO_SET_FLOW_CTRL, 0},
{"set modem control lines",
FTDI_SIO_MODEM_CTRL, 0x303}, /* DSR + CTS */
{"set baud rate divisor",
FTDI_SIO_SET_BAUD_RATE, 0xf}, /* 200 kbps */
{"set latency timer",
FTDI_SIO_SET_LATENCY_TIMER, 50}, /* 50 ms */
{"purge TX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_TX},
{"purge RX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_RX}
};
int configure_ftdi(struct usb_dev_handle *handle) static int do_cfg(struct usb_dev_handle *handle, const char *what,
int request, int value)
{ {
int i; if (usb_control_msg(handle, REQTYPE_HOST_TO_DEVICE,
request, value, 0,
for (i = 0; i < ARRAY_LEN(config); i++) { NULL, 0, REQ_TIMEOUT_MS)) {
const struct config_rec *r = &config[i]; printc_err("ftdi: %s failed: %s\n", what, usb_strerror());
return -1;
if (usb_control_msg(handle, REQTYPE_HOST_TO_DEVICE,
r->request, r->value, 0,
NULL, 0, REQ_TIMEOUT_MS)) {
printc_err("olimex_iso: %s failed: %s\n",
r->desc, usb_strerror());
return -1;
}
} }
return 0; return 0;
} }
static int open_device(struct iso_transport *tr, struct usb_device *dev) int configure_ftdi(struct usb_dev_handle *h, int baud_rate)
{
if (do_cfg(h, "reset FTDI",
FTDI_SIO_RESET, FTDI_SIO_RESET_SIO) < 0 ||
do_cfg(h, "set data characteristics",
FTDI_SIO_SET_DATA, 8) < 0 ||
do_cfg(h, "disable flow control",
FTDI_SIO_SET_FLOW_CTRL, 0) < 0 ||
do_cfg(h, "set modem control lines",
FTDI_SIO_MODEM_CTRL, 0x303) < 0 ||
do_cfg(h, "set baud rate",
FTDI_SIO_SET_BAUD_RATE, FTDI_CLOCK / baud_rate) < 0 ||
do_cfg(h, "set latency timer",
FTDI_SIO_SET_LATENCY_TIMER, 50) < 0 ||
do_cfg(h, "purge TX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_TX) < 0 ||
do_cfg(h, "purge RX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_RX) < 0)
return -1;
return 0;
}
static int open_device(struct ftdi_transport *tr, struct usb_device *dev,
int baud_rate)
{ {
#ifdef __linux__ #ifdef __linux__
int driver; int driver;
char drv_name[128]; char drv_name[128];
#endif #endif
printc_dbg("olimex_iso: trying to open %s\n", dev->filename); printc_dbg("ftdi: trying to open %s\n", dev->filename);
tr->handle = usb_open(dev); tr->handle = usb_open(dev);
if (!tr->handle) { if (!tr->handle) {
printc_err("olimex_iso: can't open device: %s\n", printc_err("ftdi: can't open device: %s\n",
usb_strerror()); usb_strerror());
return -1; return -1;
} }
@ -127,14 +125,14 @@ static int open_device(struct iso_transport *tr, struct usb_device *dev)
if (driver >= 0) { if (driver >= 0) {
printc_dbg("Detaching kernel driver \"%s\"\n", drv_name); printc_dbg("Detaching kernel driver \"%s\"\n", drv_name);
if (usb_detach_kernel_driver_np(tr->handle, USB_INTERFACE) < 0) if (usb_detach_kernel_driver_np(tr->handle, USB_INTERFACE) < 0)
printc_err("warning: olimex_iso: can't detach " printc_err("warning: ftdi: can't detach "
"kernel driver: %s\n", usb_strerror()); "kernel driver: %s\n", usb_strerror());
} }
#endif #endif
#ifdef __Windows__ #ifdef __Windows__
if (usb_set_configuration(tr->handle, USB_CONFIG) < 0) { if (usb_set_configuration(tr->handle, USB_CONFIG) < 0) {
printc_err("olimex_iso: can't set configuration: %s\n", printc_err("ftdi: can't set configuration: %s\n",
usb_strerror()); usb_strerror());
usb_close(tr->handle); usb_close(tr->handle);
return -1; return -1;
@ -142,14 +140,14 @@ static int open_device(struct iso_transport *tr, struct usb_device *dev)
#endif #endif
if (usb_claim_interface(tr->handle, USB_INTERFACE) < 0) { if (usb_claim_interface(tr->handle, USB_INTERFACE) < 0) {
printc_err("olimex_iso: can't claim interface: %s\n", printc_err("ftdi: can't claim interface: %s\n",
usb_strerror()); usb_strerror());
usb_close(tr->handle); usb_close(tr->handle);
return -1; return -1;
} }
if (configure_ftdi(tr->handle) < 0) { if (configure_ftdi(tr->handle, baud_rate) < 0) {
printc_err("olimex_iso: failed to configure device: %s\n", printc_err("ftdi: failed to configure device: %s\n",
usb_strerror()); usb_strerror());
usb_close(tr->handle); usb_close(tr->handle);
return -1; return -1;
@ -160,7 +158,7 @@ static int open_device(struct iso_transport *tr, struct usb_device *dev)
static void tr_destroy(transport_t tr_base) static void tr_destroy(transport_t tr_base)
{ {
struct iso_transport *tr = (struct iso_transport *)tr_base; struct ftdi_transport *tr = (struct ftdi_transport *)tr_base;
usb_close(tr->handle); usb_close(tr->handle);
free(tr); free(tr);
@ -168,7 +166,7 @@ static void tr_destroy(transport_t tr_base)
static int tr_recv(transport_t tr_base, uint8_t *databuf, int max_len) static int tr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
{ {
struct iso_transport *tr = (struct iso_transport *)tr_base; struct ftdi_transport *tr = (struct ftdi_transport *)tr_base;
time_t deadline = time(NULL) + TIMEOUT_S; time_t deadline = time(NULL) + TIMEOUT_S;
char tmpbuf[FTDI_PACKET_SIZE]; char tmpbuf[FTDI_PACKET_SIZE];
@ -181,7 +179,7 @@ static int tr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
TIMEOUT_S * 1000); TIMEOUT_S * 1000);
if (r <= 0) { if (r <= 0) {
printc_err("olimex_iso: usb_bulk_read: %s\n", printc_err("ftdi: usb_bulk_read: %s\n",
usb_strerror()); usb_strerror());
return -1; return -1;
} }
@ -189,24 +187,24 @@ static int tr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
if (r > 2) { if (r > 2) {
memcpy(databuf, tmpbuf + 2, r - 2); memcpy(databuf, tmpbuf + 2, r - 2);
#ifdef DEBUG_OLIMEX_ISO #ifdef DEBUG_OLIMEX_ISO
printc_dbg("olimex_iso: tr_recv: flags = %02x %02x\n", printc_dbg("ftdi: tr_recv: flags = %02x %02x\n",
tmpbuf[0], tmpbuf[1]); tmpbuf[0], tmpbuf[1]);
debug_hexdump("olimex_iso: tr_recv", databuf, r - 2); debug_hexdump("ftdi: tr_recv", databuf, r - 2);
#endif #endif
return r - 2; return r - 2;
} }
} }
printc_err("olimex_iso: timed out while receiving data\n"); printc_err("ftdi: timed out while receiving data\n");
return -1; return -1;
} }
static int tr_send(transport_t tr_base, const uint8_t *databuf, int len) static int tr_send(transport_t tr_base, const uint8_t *databuf, int len)
{ {
struct iso_transport *tr = (struct iso_transport *)tr_base; struct ftdi_transport *tr = (struct ftdi_transport *)tr_base;
#ifdef DEBUG_OLIMEX_ISO #ifdef DEBUG_OLIMEX_ISO
debug_hexdump("olimex_iso: tr_send", databuf, len); debug_hexdump("ftdi: tr_send", databuf, len);
#endif #endif
while (len) { while (len) {
int r = usb_bulk_write(tr->handle, EP_OUT, int r = usb_bulk_write(tr->handle, EP_OUT,
@ -214,7 +212,7 @@ static int tr_send(transport_t tr_base, const uint8_t *databuf, int len)
TIMEOUT_S * 1000); TIMEOUT_S * 1000);
if (r <= 0) { if (r <= 0) {
printc_err("olimex_iso: usb_bulk_write: %s\n", printc_err("ftdi: usb_bulk_write: %s\n",
usb_strerror()); usb_strerror());
return -1; return -1;
} }
@ -228,16 +226,28 @@ static int tr_send(transport_t tr_base, const uint8_t *databuf, int len)
static int tr_flush(transport_t tr_base) static int tr_flush(transport_t tr_base)
{ {
return 0; struct ftdi_transport *tr = malloc(sizeof(*tr));
return do_cfg(tr->handle, "purge RX",
FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_RX);
} }
static int tr_set_modem(transport_t tr_base, transport_modem_t state) static int tr_set_modem(transport_t tr_base, transport_modem_t state)
{ {
printc_err("olimex_iso: unsupported operation: set_modem\n"); struct ftdi_transport *tr = malloc(sizeof(*tr));
return -1; int value = FTDI_WRITE_DTR | FTDI_WRITE_RTS;
/* DTR and RTS bits are active-low for this device */
if (!(state & TRANSPORT_MODEM_DTR))
value |= FTDI_DTR;
if (!(state & TRANSPORT_MODEM_RTS))
value |= FTDI_RTS;
return do_cfg(tr->handle, "set modem control lines",
FTDI_SIO_MODEM_CTRL, value);
} }
static const struct transport_class olimex_iso_transport = { static const struct transport_class ftdi_class = {
.destroy = tr_destroy, .destroy = tr_destroy,
.send = tr_send, .send = tr_send,
.recv = tr_recv, .recv = tr_recv,
@ -245,18 +255,20 @@ static const struct transport_class olimex_iso_transport = {
.set_modem = tr_set_modem .set_modem = tr_set_modem
}; };
transport_t olimex_iso_open(const char *devpath, transport_t ftdi_open(const char *devpath,
const char *requested_serial) const char *requested_serial,
uint16_t vendor, uint16_t product,
int baud_rate)
{ {
struct iso_transport *tr = malloc(sizeof(*tr)); struct ftdi_transport *tr = malloc(sizeof(*tr));
struct usb_device *dev; struct usb_device *dev;
if (!tr) { if (!tr) {
pr_error("olimex_iso: can't allocate memory"); pr_error("ftdi: can't allocate memory");
return NULL; return NULL;
} }
tr->base.ops = &olimex_iso_transport; tr->base.ops = &ftdi_class;
usb_init(); usb_init();
usb_find_busses(); usb_find_busses();
@ -265,16 +277,15 @@ transport_t olimex_iso_open(const char *devpath,
if (devpath) if (devpath)
dev = usbutil_find_by_loc(devpath); dev = usbutil_find_by_loc(devpath);
else else
dev = usbutil_find_by_id(USB_VENDOR, USB_PRODUCT, dev = usbutil_find_by_id(vendor, product, requested_serial);
requested_serial);
if (!dev) { if (!dev) {
free(tr); free(tr);
return NULL; return NULL;
} }
if (open_device(tr, dev) < 0) { if (open_device(tr, dev, baud_rate) < 0) {
printc_err("olimex_iso: failed to open device\n"); printc_err("ftdi: failed to open device\n");
return NULL; return NULL;
} }

View File

@ -16,8 +16,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef OLIMEX_ISO_H_ #ifndef FTDI_H_
#define OLIMEX_ISO_H_ #define FTDI_H_
#include "transport.h" #include "transport.h"
@ -26,7 +26,9 @@
* *
* A particular USB device or serial number may be specified. * A particular USB device or serial number may be specified.
*/ */
transport_t olimex_iso_open(const char *usb_device, transport_t ftdi_open(const char *usb_device,
const char *requested_serial); const char *requested_serial,
uint16_t vendor, uint16_t product,
int baud_rate);
#endif #endif