From 162d1bc9510ce8f4849d804f2c95c8a3106ae618 Mon Sep 17 00:00:00 2001 From: Daniel Beer Date: Thu, 13 Sep 2012 13:55:14 +1200 Subject: [PATCH] Separate Olimex transports and drivers. The "olimex" transport has been divided into "cp210x" and "cdc_acm", each of which take a specific vendor/product combination in their constructor. Support for the MSP430-JTAG-ISO-MK2 has been moved into its own driver instance. --- Makefile | 3 +- drivers/fet.c | 48 ++++- drivers/fet.h | 1 + mspdebug.man | 3 + transport/cdc_acm.c | 324 ++++++++++++++++++++++++++++++ transport/{olimex.h => cdc_acm.h} | 14 +- transport/{olimex.c => cp210x.c} | 132 ++++++------ transport/cp210x.h | 33 +++ ui/main.c | 2 +- 9 files changed, 481 insertions(+), 79 deletions(-) create mode 100644 transport/cdc_acm.c rename transport/{olimex.h => cdc_acm.h} (72%) rename transport/{olimex.c => cp210x.c} (70%) create mode 100644 transport/cp210x.h diff --git a/Makefile b/Makefile index 03368ec..8bf2dde 100644 --- a/Makefile +++ b/Makefile @@ -114,7 +114,8 @@ OBJ=\ util/gdb_proto.o \ util/dynload.o \ util/demangle.o \ - transport/olimex.o \ + transport/cp210x.o \ + transport/cdc_acm.o \ transport/olimex_iso.o \ transport/rf2500.o \ transport/ti3410.o \ diff --git a/drivers/fet.c b/drivers/fet.c index 79be422..56b4100 100644 --- a/drivers/fet.c +++ b/drivers/fet.c @@ -35,10 +35,11 @@ #include "opdb.h" #include "uif.h" -#include "olimex.h" #include "olimex_iso.h" #include "rf2500.h" #include "ti3410.h" +#include "cp210x.h" +#include "cdc_acm.h" #include "obl.h" /* Send data in separate packets, as in the RF2500 */ @@ -1113,7 +1114,7 @@ const struct device_class device_rf2500 = { .poll = fet_poll }; -static device_t fet_open_olimex(const struct device_args *args) +static device_t fet_open_olimex_iso_mk2(const struct device_args *args) { transport_t trans; uint32_t version; @@ -1121,7 +1122,8 @@ static device_t fet_open_olimex(const struct device_args *args) if (args->flags & DEVICE_FLAG_TTY) trans = uif_open(args->path, UIF_TYPE_OLIMEX); else - trans = olimex_open(args->path, args->requested_serial); + trans = cdc_acm_open(args->path, args->requested_serial, + 115200, 0x15ba, 0x0100); if (!trans) return NULL; @@ -1143,7 +1145,9 @@ static device_t fet_open_olimex(const struct device_args *args) if (args->flags & DEVICE_FLAG_TTY) trans = uif_open(args->path, UIF_TYPE_OLIMEX); else - trans = olimex_open(args->path, args->requested_serial); + trans = cdc_acm_open(args->path, + args->requested_serial, + 115200, 0x15ba, 0x0100); if (!trans) return NULL; @@ -1152,6 +1156,39 @@ static device_t fet_open_olimex(const struct device_args *args) if (!obl_get_version(trans, &version)) printc_dbg("Olimex firmware version: %x\n", version); + return fet_open(args, FET_PROTO_NOLEAD_SEND | FET_PROTO_EXTRA_RECV | + FET_PROTO_IDENTIFY_NEW | FET_PROTO_FORCE_RESET, + trans, &device_olimex_iso_mk2); +} + +const struct device_class device_olimex_iso_mk2 = { + .name = "olimex-iso-mk2", + .help = +"Olimex MSP430-JTAG-ISO-MK2.", + .open = fet_open_olimex_iso_mk2, + .destroy = fet_destroy, + .readmem = fet_readmem, + .writemem = fet_writemem, + .erase = fet_erase, + .getregs = fet_getregs, + .setregs = fet_setregs, + .ctl = fet_ctl, + .poll = fet_poll +}; + +static device_t fet_open_olimex(const struct device_args *args) +{ + transport_t trans; + + if (args->flags & DEVICE_FLAG_TTY) + trans = uif_open(args->path, UIF_TYPE_OLIMEX); + else + trans = cdc_acm_open(args->path, args->requested_serial, + 115200, 0x15ba, 0x0031); + + if (!trans) + return NULL; + return fet_open(args, FET_PROTO_NOLEAD_SEND | FET_PROTO_EXTRA_RECV | FET_PROTO_IDENTIFY_NEW | FET_PROTO_FORCE_RESET, trans, &device_olimex); @@ -1179,7 +1216,8 @@ static device_t fet_open_olimex_v1(const struct device_args *args) if (args->flags & DEVICE_FLAG_TTY) trans = uif_open(args->path, UIF_TYPE_OLIMEX_V1); else - trans = olimex_open(args->path, args->requested_serial); + trans = cp210x_open(args->path, args->requested_serial, + 500000, 0x15ba, 0x0002); if (!trans) return NULL; diff --git a/drivers/fet.h b/drivers/fet.h index 636696c..eb9dc4d 100644 --- a/drivers/fet.h +++ b/drivers/fet.h @@ -25,6 +25,7 @@ extern const struct device_class device_rf2500; extern const struct device_class device_olimex; extern const struct device_class device_olimex_v1; extern const struct device_class device_olimex_iso; +extern const struct device_class device_olimex_iso_mk2; extern const struct device_class device_uif; #endif diff --git a/mspdebug.man b/mspdebug.man index 9dab319..8f90698 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -98,6 +98,9 @@ to a V1 device via a tty interface. .IP "\fBolimex-iso\fR" Connect to an Olimex MSP-JTAG-ISO device. Both USB and tty access are supported. +.IP "\fBolimex-iso-mk2\fR" +Connect to an Olimex MSP430-JTAG-ISO-MK2 device. Both USB and tty +access are supported. .IP "\fBsim\fR" Do not connect to any hardware device, but instead start in simulation mode. A 64k buffer is allocated to simulate the device memory. diff --git a/transport/cdc_acm.c b/transport/cdc_acm.c new file mode 100644 index 0000000..5688cfb --- /dev/null +++ b/transport/cdc_acm.c @@ -0,0 +1,324 @@ +/* MSPDebug - debugging tool for the eZ430 + * Copyright (C) 2009-2012 Daniel Beer + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "cdc_acm.h" +#include "util.h" +#include "usbutil.h" +#include "output.h" + +#define READ_BUFFER_SIZE 1024 + +struct cdc_acm_transport { + struct transport base; + + int int_number; + struct usb_dev_handle *handle; + + int in_ep; + int out_ep; + + /* We have to implement an intermediate read buffer, because + * some interfaces are buggy and don't like single-byte reads. + */ + int rbuf_len; + int rbuf_ptr; + char rbuf[READ_BUFFER_SIZE]; +}; + +#define CDC_INTERFACE_CLASS 10 + +#define TIMEOUT 10000 + +/* CDC requests */ +#define CDC_REQTYPE_HOST_TO_DEVICE 0x21 +#define CDC_SET_CONTROL 0x22 +#define CDC_SET_LINE_CODING 0x20 + +/* Modem control line bitmask */ +#define CDC_CTRL_DTR 0x01 +#define CDC_CTRL_RTS 0x02 + +static int usbtr_send(transport_t tr_base, const uint8_t *data, int len) +{ + struct cdc_acm_transport *tr = (struct cdc_acm_transport *)tr_base; + int sent; + +#ifdef DEBUG_CDC_ACM + debug_hexdump(__FILE__ ": USB transfer out", data, len); +#endif + while (len) { + sent = usb_bulk_write(tr->handle, tr->out_ep, + (char *)data, len, TIMEOUT); + if (sent <= 0) { + pr_error(__FILE__": can't send data"); + return -1; + } + + data += sent; + len -= sent; + } + + return 0; +} + +static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int len) +{ + struct cdc_acm_transport *tr = (struct cdc_acm_transport *)tr_base; + + if (tr->rbuf_ptr >= tr->rbuf_len) { + tr->rbuf_ptr = 0; + tr->rbuf_len = usb_bulk_read(tr->handle, tr->in_ep, + tr->rbuf, sizeof(tr->rbuf), + TIMEOUT); + + if (tr->rbuf_len <= 0) { + pr_error(__FILE__": can't receive data"); + return -1; + } + +#ifdef DEBUG_CDC_ACM + debug_hexdump(__FILE__": USB transfer in", + (uint8_t *)tr->rbuf, tr->rbuf_len); +#endif + } + + if (tr->rbuf_ptr + len > tr->rbuf_len) + len = tr->rbuf_len - tr->rbuf_ptr; + + memcpy(databuf, tr->rbuf + tr->rbuf_ptr, len); + tr->rbuf_ptr += len; + + return len; +} + +static void usbtr_destroy(transport_t tr_base) +{ + struct cdc_acm_transport *tr = (struct cdc_acm_transport *)tr_base; + + usb_release_interface(tr->handle, tr->int_number); + usb_close(tr->handle); + free(tr); +} + +static int usbtr_flush(transport_t tr_base) +{ + struct cdc_acm_transport *tr = (struct cdc_acm_transport *)tr_base; + char buf[64]; + + /* Flush out lingering data */ + while (usb_bulk_read(tr->handle, tr->in_ep, + buf, sizeof(buf), + 100) > 0); + + tr->rbuf_len = 0; + tr->rbuf_ptr = 0; + return 0; +} + +static int usbtr_set_modem(transport_t tr_base, transport_modem_t state) +{ + struct cdc_acm_transport *tr = (struct cdc_acm_transport *)tr_base; + int value = 0; + + if (state & TRANSPORT_MODEM_DTR) + value |= CDC_CTRL_DTR; + if (state & TRANSPORT_MODEM_RTS) + value |= CDC_CTRL_RTS; + +#ifdef DEBUG_CDC_ACM + printc(__FILE__": modem ctrl = 0x%x\n", value); +#endif + + if (usb_control_msg(tr->handle, CDC_REQTYPE_HOST_TO_DEVICE, + CDC_SET_CONTROL, value, 0, + NULL, 0, 300) < 0) { + pr_error("cdc_acm: failed to set modem control lines\n"); + return -1; + } + + return 0; +} + +static const struct transport_class cdc_acm_class = { + .destroy = usbtr_destroy, + .send = usbtr_send, + .recv = usbtr_recv, + .flush = usbtr_flush, + .set_modem = usbtr_set_modem +}; + +static int find_interface(struct cdc_acm_transport *tr, + struct usb_device *dev) +{ + struct usb_config_descriptor *c = &dev->config[0]; + int i; + + for (i = 0; i < c->bNumInterfaces; i++) { + struct usb_interface *intf = &c->interface[i]; + struct usb_interface_descriptor *desc = &intf->altsetting[0]; + int j; + + if (desc->bInterfaceClass != CDC_INTERFACE_CLASS) + continue; + + /* Look for bulk in/out endpoints */ + tr->in_ep = -1; + tr->out_ep = -1; + + for (j = 0; j < desc->bNumEndpoints; j++) { + struct usb_endpoint_descriptor *ep = + &desc->endpoint[j]; + const int type = + ep->bmAttributes & USB_ENDPOINT_TYPE_MASK; + const int addr = ep->bEndpointAddress; + + if (type != USB_ENDPOINT_TYPE_BULK) + continue; + + if (addr & USB_ENDPOINT_DIR_MASK) + tr->in_ep = addr; + else + tr->out_ep = addr; + } + + if (tr->in_ep >= 0 && tr->out_ep >= 0) { + tr->int_number = i; + return 0; + } + } + + return -1; +} + +static int open_interface(struct cdc_acm_transport *tr, + struct usb_device *dev) +{ +#if defined(__linux__) + int drv; + char drName[256]; +#endif + + tr->handle = usb_open(dev); + if (!tr->handle) { + pr_error(__FILE__": can't open device"); + return -1; + } + +#if defined(__linux__) + drv = usb_get_driver_np(tr->handle, tr->int_number, drName, + sizeof(drName)); + if (drv >= 0) { + if (usb_detach_kernel_driver_np(tr->handle, + tr->int_number) < 0) + pr_error(__FILE__": warning: can't detach " + "kernel driver"); + } +#endif + + if (usb_claim_interface(tr->handle, tr->int_number) < 0) { + pr_error(__FILE__": can't claim interface"); + usb_close(tr->handle); + return -1; + } + + return 0; +} + +static int configure_port(struct cdc_acm_transport *tr, int baud_rate) +{ + uint8_t line_coding[7]; + + line_coding[0] = baud_rate & 0xff; + line_coding[1] = (baud_rate >> 8) & 0xff; + line_coding[2] = (baud_rate >> 16) & 0xff; + line_coding[3] = (baud_rate >> 24) & 0xff; + line_coding[4] = 0; /* 1 stop bit */ + line_coding[5] = 0; /* no parity */ + line_coding[6] = 8; /* 8 data bits */ + + if (usb_control_msg(tr->handle, CDC_REQTYPE_HOST_TO_DEVICE, + CDC_SET_LINE_CODING, 0, 0, + (char *)line_coding, 7, 300) < 0) { + pr_error("cdc_acm: failed to set line coding\n"); + return -1; + } + + if (usb_control_msg(tr->handle, CDC_REQTYPE_HOST_TO_DEVICE, + CDC_SET_CONTROL, 0, 0, NULL, 0, 300) < 0) { + pr_error("cdc_acm: failed to set modem control lines\n"); + return -1; + } + + return 0; +} + +transport_t cdc_acm_open(const char *devpath, const char *requested_serial, + int baud_rate, uint16_t vendor, uint16_t product) +{ + struct cdc_acm_transport *tr = malloc(sizeof(*tr)); + struct usb_device *dev; + + if (!tr) { + pr_error(__FILE__": can't allocate memory"); + return NULL; + } + + tr->base.ops = &cdc_acm_class; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + if (devpath) + dev = usbutil_find_by_loc(devpath); + else + dev = usbutil_find_by_id(vendor, product, requested_serial); + + if (!dev) { + free(tr); + return NULL; + } + + if (find_interface(tr, dev) < 0) { + printc_err(__FILE__ ": failed to locate CDC-ACM interface\n"); + free(tr); + return NULL; + } + + if (open_interface(tr, dev) < 0) { + printc_err(__FILE__": failed to open interface\n"); + free(tr); + return NULL; + } + + if (configure_port(tr, baud_rate) < 0) { + usb_release_interface(tr->handle, tr->int_number); + usb_close(tr->handle); + free(tr); + return NULL; + } + + usbtr_flush(&tr->base); + + return (transport_t)tr; +} diff --git a/transport/olimex.h b/transport/cdc_acm.h similarity index 72% rename from transport/olimex.h rename to transport/cdc_acm.h index fe4060c..4e1365c 100644 --- a/transport/olimex.h +++ b/transport/cdc_acm.h @@ -1,5 +1,5 @@ /* MSPDebug - debugging tool for MSP430 MCUs - * Copyright (C) 2009, 2010 Daniel Beer + * Copyright (C) 2009-2012 Daniel Beer * Copyright (C) 2010 Peter Jansen * * This program is free software; you can redistribute it and/or modify @@ -17,17 +17,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef OLIMEX_H_ -#define OLIMEX_H_ +#ifndef CDC_ACM_H_ +#define CDC_ACM_H_ #include "transport.h" -/* Search the USB bus for the first Olimex MSP-JTAG-TINY, and - * initialize it. If successful, 0 is returned and the fet_* functions - * are ready for use. If an error occurs, -1 is returned. +/* Search the USB bus for the first CDC-ACM device, and initialize it. + * If successful, return a valid transport object. * * A particular USB device may be specified in bus:dev form. */ -transport_t olimex_open(const char *usb_device, const char *requested_serial); +transport_t cdc_acm_open(const char *usb_device, const char *requested_serial, + int baud_rate, uint16_t product, uint16_t vendor); #endif diff --git a/transport/olimex.c b/transport/cp210x.c similarity index 70% rename from transport/olimex.c rename to transport/cp210x.c index 81c073b..a78ae6e 100644 --- a/transport/olimex.c +++ b/transport/cp210x.c @@ -22,23 +22,16 @@ #include #include -#include "olimex.h" +#include "cp210x.h" #include "util.h" #include "usbutil.h" #include "output.h" -struct olimex_transport { +struct cp210x_transport { struct transport base; - int int_number; struct usb_dev_handle *handle; - - int in_ep; - int out_ep; - - uint8_t buf[64]; - int len; - int offset; + int int_number; }; /********************************************************************* @@ -52,33 +45,37 @@ struct olimex_transport { * one transfer. */ -#define USB_FET_VENDOR 0x15ba +#define CP210X_CLOCK 35000000 -#define V1_PRODUCT 0x0002 #define V1_INTERFACE_CLASS 255 #define V1_IN_EP 0x81 #define V1_OUT_EP 0x01 -#define V2_PRODUCT 0x0031 -#define V2_INTERFACE_CLASS 10 -#define V2_IN_EP 0x82 -#define V2_OUT_EP 0x02 - #define CP210x_REQTYPE_HOST_TO_DEVICE 0x41 #define CP210X_IFC_ENABLE 0x00 #define CP210X_SET_BAUDDIV 0x01 #define CP210X_SET_MHS 0x07 +/* CP210X_(SET_MHS|GET_MDMSTS) */ +#define CP210X_DTR 0x0001 +#define CP210X_RTS 0x0002 +#define CP210X_CTS 0x0010 +#define CP210X_DSR 0x0020 +#define CP210X_RING 0x0040 +#define CP210X_DCD 0x0080 +#define CP210X_WRITE_DTR 0x0100 +#define CP210X_WRITE_RTS 0x0200 + #define TIMEOUT 10000 -static int v1_configure(struct olimex_transport *tr) +static int configure_port(struct cp210x_transport *tr, int baud_rate) { int ret; ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE, CP210X_IFC_ENABLE, 0x1, 0, NULL, 0, 300); -#ifdef DEBUG_OLIMEX +#ifdef DEBUG_CP210X printc("%s: %s: Sending control message " "CP210x_REQTYPE_HOST_TO_DEVICE, ret = %d\n", __FILE__, __FUNCTION__, ret); @@ -90,8 +87,9 @@ static int v1_configure(struct olimex_transport *tr) /* Set the baud rate to 500000 bps */ ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE, - CP210X_SET_BAUDDIV, 0x7, 0, NULL, 0, 300); -#ifdef DEBUG_OLIMEX + CP210X_SET_BAUDDIV, CP210X_CLOCK / baud_rate, + 0, NULL, 0, 300); +#ifdef DEBUG_CP210X printc("%s: %s: Sending control message " "CP210X_SET_BAUDDIV, ret = %d\n", __FILE__, __FUNCTION__, ret); @@ -102,11 +100,11 @@ static int v1_configure(struct olimex_transport *tr) } /* Set the modem control settings. - * Set RTS, DTR and WRITE_DTR, WRITE_RTS + * Clear RTS, DTR and WRITE_DTR, WRITE_RTS */ ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE, CP210X_SET_MHS, 0x303, 0, NULL, 0, 300); -#ifdef DEBUG_OLIMEX +#ifdef DEBUG_CP210X printc("%s: %s: Sending control message " "CP210X_SET_MHS, ret %d\n", __FILE__, __FUNCTION__, ret); @@ -119,8 +117,9 @@ static int v1_configure(struct olimex_transport *tr) return 0; } -static int open_interface(struct olimex_transport *tr, - struct usb_device *dev, int ino) +static int open_interface(struct cp210x_transport *tr, + struct usb_device *dev, int ino, + int baud_rate) { #if defined(__linux__) int drv; @@ -164,7 +163,7 @@ static int open_interface(struct olimex_transport *tr, return -1; } - if (dev->descriptor.idProduct == V1_PRODUCT && v1_configure(tr) < 0) { + if (configure_port(tr, baud_rate) < 0) { printc_err("Failed to configure for V1 device\n"); usb_close(tr->handle); return -1; @@ -173,7 +172,8 @@ static int open_interface(struct olimex_transport *tr, return 0; } -static int open_device(struct olimex_transport *tr, struct usb_device *dev) +static int open_device(struct cp210x_transport *tr, struct usb_device *dev, + int baud_rate) { struct usb_config_descriptor *c = &dev->config[0]; int i; @@ -183,18 +183,9 @@ static int open_device(struct olimex_transport *tr, struct usb_device *dev) struct usb_interface_descriptor *desc = &intf->altsetting[0]; if (desc->bInterfaceClass == V1_INTERFACE_CLASS && - !open_interface(tr, dev, desc->bInterfaceNumber)) { - printc_dbg("olimex: rev 1 device\n"); - tr->in_ep = V1_IN_EP; - tr->out_ep = V1_OUT_EP; + !open_interface(tr, dev, desc->bInterfaceNumber, + baud_rate)) return 0; - } else if (desc->bInterfaceClass == V2_INTERFACE_CLASS && - !open_interface(tr, dev, desc->bInterfaceNumber)) { - printc_dbg("olimex: rev 2 device\n"); - tr->in_ep = V2_IN_EP; - tr->out_ep = V2_OUT_EP; - return 0; - } } return -1; @@ -202,14 +193,14 @@ static int open_device(struct olimex_transport *tr, struct usb_device *dev) static int usbtr_send(transport_t tr_base, const uint8_t *data, int len) { - struct olimex_transport *tr = (struct olimex_transport *)tr_base; + struct cp210x_transport *tr = (struct cp210x_transport *)tr_base; int sent; -#ifdef DEBUG_OLIMEX +#ifdef DEBUG_CP210X debug_hexdump(__FILE__ ": USB transfer out", data, len); #endif while (len) { - sent = usb_bulk_write(tr->handle, tr->out_ep, + sent = usb_bulk_write(tr->handle, V1_OUT_EP, (char *)data, len, TIMEOUT); if (sent <= 0) { pr_error(__FILE__": can't send data"); @@ -225,17 +216,17 @@ static int usbtr_send(transport_t tr_base, const uint8_t *data, int len) static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int max_len) { - struct olimex_transport *tr = (struct olimex_transport *)tr_base; + struct cp210x_transport *tr = (struct cp210x_transport *)tr_base; int rlen; -#ifdef DEBUG_OLIMEX +#ifdef DEBUG_CP210X printc(__FILE__": %s : read max %d\n", __FUNCTION__, max_len); #endif - rlen = usb_bulk_read(tr->handle, tr->in_ep, (char *)databuf, + rlen = usb_bulk_read(tr->handle, V1_IN_EP, (char *)databuf, max_len, TIMEOUT); -#ifdef DEBUG_OLIMEX +#ifdef DEBUG_CP210X printc(__FILE__": %s : read %d\n", __FUNCTION__, rlen); #endif @@ -244,7 +235,7 @@ static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int max_len) return -1; } -#ifdef DEBUG_OLIMEX +#ifdef DEBUG_CP210X debug_hexdump(__FILE__": USB transfer in", databuf, rlen); #endif @@ -253,7 +244,7 @@ static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int max_len) static void usbtr_destroy(transport_t tr_base) { - struct olimex_transport *tr = (struct olimex_transport *)tr_base; + struct cp210x_transport *tr = (struct cp210x_transport *)tr_base; usb_release_interface(tr->handle, tr->int_number); usb_close(tr->handle); @@ -262,11 +253,11 @@ static void usbtr_destroy(transport_t tr_base) static int usbtr_flush(transport_t tr_base) { - struct olimex_transport *tr = (struct olimex_transport *)tr_base; + struct cp210x_transport *tr = (struct cp210x_transport *)tr_base; char buf[64]; /* Flush out lingering data */ - while (usb_bulk_read(tr->handle, tr->in_ep, + while (usb_bulk_read(tr->handle, V1_IN_EP, buf, sizeof(buf), 100) > 0); @@ -275,11 +266,25 @@ static int usbtr_flush(transport_t tr_base) static int usbtr_set_modem(transport_t tr_base, transport_modem_t state) { - printc_err("olimex: unsupported operation: set_modem\n"); - return -1; + struct cp210x_transport *tr = (struct cp210x_transport *)tr_base; + int value = CP210X_WRITE_DTR | CP210X_WRITE_RTS; + + /* DTR and RTS bits are active-low for this device */ + if (!(state & TRANSPORT_MODEM_DTR)) + value |= CP210X_DTR; + if (!(state & TRANSPORT_MODEM_RTS)) + value |= CP210X_RTS; + + if (usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE, + CP210X_SET_MHS, value, 0, NULL, 0, 300) < 0) { + pr_error("cp210x: failed to set modem control lines\n"); + return -1; + } + + return 0; } -static const struct transport_class olimex_transport = { +static const struct transport_class cp210x_class = { .destroy = usbtr_destroy, .send = usbtr_send, .recv = usbtr_recv, @@ -287,9 +292,10 @@ static const struct transport_class olimex_transport = { .set_modem = usbtr_set_modem }; -transport_t olimex_open(const char *devpath, const char *requested_serial) +transport_t cp210x_open(const char *devpath, const char *requested_serial, + int baud_rate, uint16_t product, uint16_t vendor) { - struct olimex_transport *tr = malloc(sizeof(*tr)); + struct cp210x_transport *tr = malloc(sizeof(*tr)); struct usb_device *dev; if (!tr) { @@ -297,29 +303,25 @@ transport_t olimex_open(const char *devpath, const char *requested_serial) return NULL; } - tr->base.ops = &olimex_transport; + tr->base.ops = &cp210x_class; usb_init(); usb_find_busses(); usb_find_devices(); - if (devpath) { + if (devpath) dev = usbutil_find_by_loc(devpath); - } else { - dev = usbutil_find_by_id(USB_FET_VENDOR, V1_PRODUCT, - requested_serial); - if (!dev) - dev = usbutil_find_by_id(USB_FET_VENDOR, V2_PRODUCT, - requested_serial); - } + else + dev = usbutil_find_by_id(product, vendor, requested_serial); if (!dev) { free(tr); return NULL; } - if (open_device(tr, dev) < 0) { - printc_err(__FILE__ ": failed to open Olimex device\n"); + if (open_device(tr, dev, baud_rate) < 0) { + printc_err(__FILE__ ": failed to open CP210X device\n"); + free(tr); return NULL; } diff --git a/transport/cp210x.h b/transport/cp210x.h new file mode 100644 index 0000000..3229975 --- /dev/null +++ b/transport/cp210x.h @@ -0,0 +1,33 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2012 Daniel Beer + * Copyright (C) 2010 Peter Jansen + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CP210X_H_ +#define CP210X_H_ + +#include "transport.h" + +/* Search the USB bus for the first CP210x device, and initialize it. If + * successful, a valid transport is returned. + * + * A particular USB device may be specified in bus:dev form. + */ +transport_t cp210x_open(const char *usb_device, const char *requested_serial, + int baud_rate, uint16_t product, uint16_t vendor); + +#endif diff --git a/ui/main.c b/ui/main.c index 1ef46f2..732ebe0 100644 --- a/ui/main.c +++ b/ui/main.c @@ -48,7 +48,6 @@ #include "gdbc.h" #include "uif.h" -#include "olimex.h" #include "rf2500.h" #include "tilib.h" #include "goodfet.h" @@ -64,6 +63,7 @@ static const struct device_class *const driver_table[] = { &device_olimex, &device_olimex_v1, &device_olimex_iso, + &device_olimex_iso_mk2, &device_sim, &device_uif, &device_bsl,