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.
This commit is contained in:
Daniel Beer 2012-09-13 13:55:14 +12:00
parent 6037c12291
commit 162d1bc951
9 changed files with 481 additions and 79 deletions

View File

@ -114,7 +114,8 @@ 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/cp210x.o \
transport/cdc_acm.o \
transport/olimex_iso.o \ transport/olimex_iso.o \
transport/rf2500.o \ transport/rf2500.o \
transport/ti3410.o \ transport/ti3410.o \

View File

@ -35,10 +35,11 @@
#include "opdb.h" #include "opdb.h"
#include "uif.h" #include "uif.h"
#include "olimex.h"
#include "olimex_iso.h" #include "olimex_iso.h"
#include "rf2500.h" #include "rf2500.h"
#include "ti3410.h" #include "ti3410.h"
#include "cp210x.h"
#include "cdc_acm.h"
#include "obl.h" #include "obl.h"
/* Send data in separate packets, as in the RF2500 */ /* Send data in separate packets, as in the RF2500 */
@ -1113,7 +1114,7 @@ const struct device_class device_rf2500 = {
.poll = fet_poll .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; transport_t trans;
uint32_t version; uint32_t version;
@ -1121,7 +1122,8 @@ static device_t fet_open_olimex(const struct device_args *args)
if (args->flags & DEVICE_FLAG_TTY) if (args->flags & DEVICE_FLAG_TTY)
trans = uif_open(args->path, UIF_TYPE_OLIMEX); trans = uif_open(args->path, UIF_TYPE_OLIMEX);
else else
trans = olimex_open(args->path, args->requested_serial); trans = cdc_acm_open(args->path, args->requested_serial,
115200, 0x15ba, 0x0100);
if (!trans) if (!trans)
return NULL; return NULL;
@ -1143,7 +1145,9 @@ static device_t fet_open_olimex(const struct device_args *args)
if (args->flags & DEVICE_FLAG_TTY) if (args->flags & DEVICE_FLAG_TTY)
trans = uif_open(args->path, UIF_TYPE_OLIMEX); trans = uif_open(args->path, UIF_TYPE_OLIMEX);
else else
trans = olimex_open(args->path, args->requested_serial); trans = cdc_acm_open(args->path,
args->requested_serial,
115200, 0x15ba, 0x0100);
if (!trans) if (!trans)
return NULL; return NULL;
@ -1152,6 +1156,39 @@ static device_t fet_open_olimex(const struct device_args *args)
if (!obl_get_version(trans, &version)) if (!obl_get_version(trans, &version))
printc_dbg("Olimex firmware version: %x\n", 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 | return fet_open(args, FET_PROTO_NOLEAD_SEND | FET_PROTO_EXTRA_RECV |
FET_PROTO_IDENTIFY_NEW | FET_PROTO_FORCE_RESET, FET_PROTO_IDENTIFY_NEW | FET_PROTO_FORCE_RESET,
trans, &device_olimex); 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) if (args->flags & DEVICE_FLAG_TTY)
trans = uif_open(args->path, UIF_TYPE_OLIMEX_V1); trans = uif_open(args->path, UIF_TYPE_OLIMEX_V1);
else else
trans = olimex_open(args->path, args->requested_serial); trans = cp210x_open(args->path, args->requested_serial,
500000, 0x15ba, 0x0002);
if (!trans) if (!trans)
return NULL; return NULL;

View File

@ -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;
extern const struct device_class device_olimex_v1; extern const struct device_class device_olimex_v1;
extern const struct device_class device_olimex_iso; extern const struct device_class device_olimex_iso;
extern const struct device_class device_olimex_iso_mk2;
extern const struct device_class device_uif; extern const struct device_class device_uif;
#endif #endif

View File

@ -98,6 +98,9 @@ to a V1 device via a tty interface.
.IP "\fBolimex-iso\fR" .IP "\fBolimex-iso\fR"
Connect to an Olimex MSP-JTAG-ISO device. Both USB and tty access are Connect to an Olimex MSP-JTAG-ISO device. Both USB and tty access are
supported. 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" .IP "\fBsim\fR"
Do not connect to any hardware device, but instead start in simulation Do not connect to any hardware device, but instead start in simulation
mode. A 64k buffer is allocated to simulate the device memory. mode. A 64k buffer is allocated to simulate the device memory.

324
transport/cdc_acm.c Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <usb.h>
#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;
}

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
* 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
@ -17,17 +17,17 @@
* 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_H_ #ifndef CDC_ACM_H_
#define OLIMEX_H_ #define CDC_ACM_H_
#include "transport.h" #include "transport.h"
/* Search the USB bus for the first Olimex MSP-JTAG-TINY, and /* Search the USB bus for the first CDC-ACM device, and initialize it.
* initialize it. If successful, 0 is returned and the fet_* functions * If successful, return a valid transport object.
* are ready for use. If an error occurs, -1 is returned.
* *
* A particular USB device may be specified in bus:dev form. * 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 #endif

View File

@ -22,23 +22,16 @@
#include <string.h> #include <string.h>
#include <usb.h> #include <usb.h>
#include "olimex.h" #include "cp210x.h"
#include "util.h" #include "util.h"
#include "usbutil.h" #include "usbutil.h"
#include "output.h" #include "output.h"
struct olimex_transport { struct cp210x_transport {
struct transport base; struct transport base;
int int_number;
struct usb_dev_handle *handle; struct usb_dev_handle *handle;
int int_number;
int in_ep;
int out_ep;
uint8_t buf[64];
int len;
int offset;
}; };
/********************************************************************* /*********************************************************************
@ -52,33 +45,37 @@ struct olimex_transport {
* one transfer. * one transfer.
*/ */
#define USB_FET_VENDOR 0x15ba #define CP210X_CLOCK 35000000
#define V1_PRODUCT 0x0002
#define V1_INTERFACE_CLASS 255 #define V1_INTERFACE_CLASS 255
#define V1_IN_EP 0x81 #define V1_IN_EP 0x81
#define V1_OUT_EP 0x01 #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_REQTYPE_HOST_TO_DEVICE 0x41
#define CP210X_IFC_ENABLE 0x00 #define CP210X_IFC_ENABLE 0x00
#define CP210X_SET_BAUDDIV 0x01 #define CP210X_SET_BAUDDIV 0x01
#define CP210X_SET_MHS 0x07 #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 #define TIMEOUT 10000
static int v1_configure(struct olimex_transport *tr) static int configure_port(struct cp210x_transport *tr, int baud_rate)
{ {
int ret; int ret;
ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE, ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE,
CP210X_IFC_ENABLE, 0x1, 0, NULL, 0, 300); CP210X_IFC_ENABLE, 0x1, 0, NULL, 0, 300);
#ifdef DEBUG_OLIMEX #ifdef DEBUG_CP210X
printc("%s: %s: Sending control message " printc("%s: %s: Sending control message "
"CP210x_REQTYPE_HOST_TO_DEVICE, ret = %d\n", "CP210x_REQTYPE_HOST_TO_DEVICE, ret = %d\n",
__FILE__, __FUNCTION__, ret); __FILE__, __FUNCTION__, ret);
@ -90,8 +87,9 @@ static int v1_configure(struct olimex_transport *tr)
/* Set the baud rate to 500000 bps */ /* Set the baud rate to 500000 bps */
ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE, ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE,
CP210X_SET_BAUDDIV, 0x7, 0, NULL, 0, 300); CP210X_SET_BAUDDIV, CP210X_CLOCK / baud_rate,
#ifdef DEBUG_OLIMEX 0, NULL, 0, 300);
#ifdef DEBUG_CP210X
printc("%s: %s: Sending control message " printc("%s: %s: Sending control message "
"CP210X_SET_BAUDDIV, ret = %d\n", "CP210X_SET_BAUDDIV, ret = %d\n",
__FILE__, __FUNCTION__, ret); __FILE__, __FUNCTION__, ret);
@ -102,11 +100,11 @@ static int v1_configure(struct olimex_transport *tr)
} }
/* Set the modem control settings. /* 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, ret = usb_control_msg(tr->handle, CP210x_REQTYPE_HOST_TO_DEVICE,
CP210X_SET_MHS, 0x303, 0, NULL, 0, 300); CP210X_SET_MHS, 0x303, 0, NULL, 0, 300);
#ifdef DEBUG_OLIMEX #ifdef DEBUG_CP210X
printc("%s: %s: Sending control message " printc("%s: %s: Sending control message "
"CP210X_SET_MHS, ret %d\n", "CP210X_SET_MHS, ret %d\n",
__FILE__, __FUNCTION__, ret); __FILE__, __FUNCTION__, ret);
@ -119,8 +117,9 @@ static int v1_configure(struct olimex_transport *tr)
return 0; return 0;
} }
static int open_interface(struct olimex_transport *tr, static int open_interface(struct cp210x_transport *tr,
struct usb_device *dev, int ino) struct usb_device *dev, int ino,
int baud_rate)
{ {
#if defined(__linux__) #if defined(__linux__)
int drv; int drv;
@ -164,7 +163,7 @@ static int open_interface(struct olimex_transport *tr,
return -1; 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"); printc_err("Failed to configure for V1 device\n");
usb_close(tr->handle); usb_close(tr->handle);
return -1; return -1;
@ -173,7 +172,8 @@ static int open_interface(struct olimex_transport *tr,
return 0; 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]; struct usb_config_descriptor *c = &dev->config[0];
int i; 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]; struct usb_interface_descriptor *desc = &intf->altsetting[0];
if (desc->bInterfaceClass == V1_INTERFACE_CLASS && if (desc->bInterfaceClass == V1_INTERFACE_CLASS &&
!open_interface(tr, dev, desc->bInterfaceNumber)) { !open_interface(tr, dev, desc->bInterfaceNumber,
printc_dbg("olimex: rev 1 device\n"); baud_rate))
tr->in_ep = V1_IN_EP;
tr->out_ep = V1_OUT_EP;
return 0; 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; 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) 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; int sent;
#ifdef DEBUG_OLIMEX #ifdef DEBUG_CP210X
debug_hexdump(__FILE__ ": USB transfer out", data, len); debug_hexdump(__FILE__ ": USB transfer out", data, len);
#endif #endif
while (len) { while (len) {
sent = usb_bulk_write(tr->handle, tr->out_ep, sent = usb_bulk_write(tr->handle, V1_OUT_EP,
(char *)data, len, TIMEOUT); (char *)data, len, TIMEOUT);
if (sent <= 0) { if (sent <= 0) {
pr_error(__FILE__": can't send data"); 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) 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; int rlen;
#ifdef DEBUG_OLIMEX #ifdef DEBUG_CP210X
printc(__FILE__": %s : read max %d\n", __FUNCTION__, max_len); printc(__FILE__": %s : read max %d\n", __FUNCTION__, max_len);
#endif #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); max_len, TIMEOUT);
#ifdef DEBUG_OLIMEX #ifdef DEBUG_CP210X
printc(__FILE__": %s : read %d\n", __FUNCTION__, rlen); printc(__FILE__": %s : read %d\n", __FUNCTION__, rlen);
#endif #endif
@ -244,7 +235,7 @@ static int usbtr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
return -1; return -1;
} }
#ifdef DEBUG_OLIMEX #ifdef DEBUG_CP210X
debug_hexdump(__FILE__": USB transfer in", databuf, rlen); debug_hexdump(__FILE__": USB transfer in", databuf, rlen);
#endif #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) 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_release_interface(tr->handle, tr->int_number);
usb_close(tr->handle); usb_close(tr->handle);
@ -262,11 +253,11 @@ static void usbtr_destroy(transport_t tr_base)
static int usbtr_flush(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]; char buf[64];
/* Flush out lingering data */ /* 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), buf, sizeof(buf),
100) > 0); 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) static int usbtr_set_modem(transport_t tr_base, transport_modem_t state)
{ {
printc_err("olimex: unsupported operation: set_modem\n"); 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 -1;
} }
static const struct transport_class olimex_transport = { return 0;
}
static const struct transport_class cp210x_class = {
.destroy = usbtr_destroy, .destroy = usbtr_destroy,
.send = usbtr_send, .send = usbtr_send,
.recv = usbtr_recv, .recv = usbtr_recv,
@ -287,9 +292,10 @@ static const struct transport_class olimex_transport = {
.set_modem = usbtr_set_modem .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; struct usb_device *dev;
if (!tr) { if (!tr) {
@ -297,29 +303,25 @@ transport_t olimex_open(const char *devpath, const char *requested_serial)
return NULL; return NULL;
} }
tr->base.ops = &olimex_transport; tr->base.ops = &cp210x_class;
usb_init(); usb_init();
usb_find_busses(); usb_find_busses();
usb_find_devices(); usb_find_devices();
if (devpath) { if (devpath)
dev = usbutil_find_by_loc(devpath); dev = usbutil_find_by_loc(devpath);
} else { else
dev = usbutil_find_by_id(USB_FET_VENDOR, V1_PRODUCT, dev = usbutil_find_by_id(product, vendor, requested_serial);
requested_serial);
if (!dev)
dev = usbutil_find_by_id(USB_FET_VENDOR, V2_PRODUCT,
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(__FILE__ ": failed to open Olimex device\n"); printc_err(__FILE__ ": failed to open CP210X device\n");
free(tr);
return NULL; return NULL;
} }

33
transport/cp210x.h Normal file
View File

@ -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

View File

@ -48,7 +48,6 @@
#include "gdbc.h" #include "gdbc.h"
#include "uif.h" #include "uif.h"
#include "olimex.h"
#include "rf2500.h" #include "rf2500.h"
#include "tilib.h" #include "tilib.h"
#include "goodfet.h" #include "goodfet.h"
@ -64,6 +63,7 @@ static const struct device_class *const driver_table[] = {
&device_olimex, &device_olimex,
&device_olimex_v1, &device_olimex_v1,
&device_olimex_iso, &device_olimex_iso,
&device_olimex_iso_mk2,
&device_sim, &device_sim,
&device_uif, &device_uif,
&device_bsl, &device_bsl,