Added support for multiple instances of USB devices.

This commit is contained in:
Daniel Beer 2010-06-28 15:13:51 +12:00
parent 8503cc4a85
commit 4824ab7750
9 changed files with 245 additions and 49 deletions

View File

@ -45,7 +45,8 @@ install: mspdebug mspdebug.man
mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
util.o bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.o \
cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o fet_db.o
cproc.o vector.o cproc_util.o expr.o fet_error.o binfile.o fet_db.o \
usbutil.o
$(CC) $(LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
.c.o:

32
main.c
View File

@ -29,6 +29,7 @@
#include "binfile.h"
#include "stab.h"
#include "util.h"
#include "usbutil.h"
#include "gdb.h"
#include "rtools.h"
#include "sym.h"
@ -121,6 +122,7 @@ static void store_io(void *user_data, uint16_t pc,
struct cmdline_args {
const char *driver_name;
const char *serial_device;
const char *usb_device;
const char *fet_force_id;
int want_jtag;
int no_rc;
@ -160,7 +162,7 @@ static device_t driver_open_rf2500(const struct cmdline_args *args)
return NULL;
}
trans = rf2500_open();
trans = rf2500_open(args->usb_device);
if (!trans)
return NULL;
@ -174,7 +176,7 @@ static device_t driver_open_olimex(const struct cmdline_args *args)
if (args->serial_device)
trans = uif_open(args->serial_device, 1);
else
trans = olimex_open();
trans = olimex_open(args->usb_device);
if (!trans)
return NULL;
@ -252,6 +254,8 @@ static void usage(const char *progname)
"\n"
" -d device\n"
" Connect via the given tty device, rather than USB.\n"
" -U bus:dev\n"
" Specify a particular USB device to connect to.\n"
" -j\n"
" Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n"
" -v voltage\n"
@ -264,9 +268,11 @@ static void usage(const char *progname)
" Show a list of devices supported by the FET driver.\n"
" --fet-force-id string\n"
" Override the device ID returned by the FET.\n"
" --usb-list\n"
" Show a list of available USB devices.\n"
"\n"
"Most drivers connect by default via USB, unless told otherwise via the\n"
"-d option.\n"
"-d option. By default, the first USB device found is opened.\n"
"\n"
"If commands are given, they will be executed. Otherwise, an interactive\n"
"command reader is started.\n\n",
@ -335,16 +341,28 @@ static int parse_cmdline_args(int argc, char **argv,
{"help", 0, 0, 'H'},
{"fet-list", 0, 0, 'L'},
{"fet-force-id", 1, 0, 'F'},
{"usb-list", 0, 0, 'I'},
{NULL, 0, 0, 0}
};
while ((opt = getopt_long(argc, argv, "d:jv:n",
while ((opt = getopt_long(argc, argv, "d:jv:nU:",
longopts, NULL)) >= 0)
switch (opt) {
case 'I':
usb_init();
usb_find_busses();
usb_find_devices();
usbutil_list();
exit(0);
case 'd':
args->serial_device = optarg;
break;
case 'U':
args->usb_device = optarg;
break;
case 'L':
exit(list_devices());
@ -373,6 +391,12 @@ static int parse_cmdline_args(int argc, char **argv,
return -1;
}
if (args->usb_device && args->serial_device) {
fprintf(stderr, "You can't simultaneously specify a serial and "
"a USB device.\n");
return -1;
}
if (optind >= argc) {
fprintf(stderr, "You need to specify a driver. Try --help for "
"a list.\n");

View File

@ -40,6 +40,9 @@ option only works on FET430UIF devices.
Specify that the driver should connect via a tty device rather than USB.
The supported connection methods vary depending on the driver. See the
section \fBDRIVERS\fR below for details.
.IP "\-U \fIbus\fR:\fIdevice\fR"
Specify a particular USB device to connect to. Without this option,
the first device of the appropriate type is opened.
.IP "\-n"
Do not process the startup file (~/.mspdebug).
.IP "\-\-help"
@ -51,6 +54,8 @@ for \fB\-R\fR and \fB\-u\fR operating modes).
When using a FET device, force the connected chip to be recognised by
MSPDebug as one of the given type during initialization. This overrides
the device ID returned by the FET.
.IP "\-\-usb\-list"
List available USB devices and exit.
.SH DRIVERS
A driver name must be specified on the command line for MSPDebug to
connect to. Valid driver names are listed here.

View File

@ -23,6 +23,7 @@
#include "olimex.h"
#include "util.h"
#include "usbutil.h"
struct olimex_transport {
struct transport base;
@ -190,10 +191,11 @@ static void usbtr_destroy(transport_t tr_base)
free(tr);
}
transport_t olimex_open(void)
transport_t olimex_open(const char *devpath)
{
struct olimex_transport *tr = malloc(sizeof(*tr));
struct usb_bus *bus;
struct usb_device *dev;
char buf[64];
if (!tr) {
perror(__FILE__": can't allocate memory");
@ -208,26 +210,25 @@ transport_t olimex_open(void)
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
if (devpath)
dev = usbutil_find_by_loc(devpath);
else
dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT);
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == USB_FET_VENDOR &&
dev->descriptor.idProduct == USB_FET_PRODUCT &&
!open_device(tr, dev)) {
char buf[64];
/* Flush out lingering data */
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) >= 0);
return (transport_t)tr;
}
}
if (!dev) {
free(tr);
return NULL;
}
fprintf(stderr, __FILE__": no devices could be found\n");
free(tr);
return NULL;
if (open_device(tr, dev) < 0) {
fprintf(stderr, __FILE__ ": failed to open Olimex device\n");
return NULL;
}
/* Flush out lingering data */
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) >= 0);
return (transport_t)tr;
}

View File

@ -25,7 +25,9 @@
/* 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.
*
* A particular USB device may be specified in bus:dev form.
*/
transport_t olimex_open(void);
transport_t olimex_open(const char *usb_device);
#endif

View File

@ -22,6 +22,7 @@
#include "rf2500.h"
#include "util.h"
#include "usbutil.h"
struct rf2500_transport {
struct transport base;
@ -177,10 +178,11 @@ static void usbtr_destroy(transport_t tr_base)
free(tr);
}
transport_t rf2500_open(void)
transport_t rf2500_open(const char *devpath)
{
struct rf2500_transport *tr = malloc(sizeof(*tr));
struct usb_bus *bus;
struct usb_device *dev;
char buf[64];
if (!tr) {
perror("rf2500: can't allocate memory");
@ -195,26 +197,25 @@ transport_t rf2500_open(void)
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
if (devpath)
dev = usbutil_find_by_loc(devpath);
else
dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT);
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == USB_FET_VENDOR &&
dev->descriptor.idProduct == USB_FET_PRODUCT &&
!open_device(tr, dev)) {
char buf[64];
/* Flush out lingering data */
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) >= 0);
return (transport_t)tr;
}
}
if (!dev) {
free(tr);
return NULL;
}
fprintf(stderr, "rf2500: no devices could be found\n");
free(tr);
return NULL;
if (open_device(tr, dev) < 0) {
fprintf(stderr, "rf2500: failed to open RF2500 device\n");
return NULL;
}
/* Flush out lingering data */
while (usb_bulk_read(tr->handle, USB_FET_IN_EP,
buf, sizeof(buf),
100) >= 0);
return (transport_t)tr;
}

View File

@ -24,7 +24,9 @@
/* Search the USB bus for the first eZ430-RF2500, and initialize it. If
* successful, 0 is returned and the fet_* functions are ready for use.
* If an error occurs, -1 is returned.
*
* A particular device may be specified in bus:dev form.
*/
transport_t rf2500_open(void);
transport_t rf2500_open(const char *dev_path);
#endif

127
usbutil.c Normal file
View File

@ -0,0 +1,127 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 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 <string.h>
#include "usbutil.h"
#include "util.h"
static const char *device_help(const struct usb_device *dev)
{
static const struct {
int vendor;
int product;
const char *help;
} info[] = {
{0x0451, 0xf432, "eZ430-RF2500"},
{0x15ba, 0x0002, "Olimex MSP-JTAG-TINY"}
};
int i;
for (i = 0; i < ARRAY_LEN(info); i++)
if (dev->descriptor.idProduct == info[i].product &&
dev->descriptor.idVendor == info[i].vendor)
return info[i].help;
return "";
}
void usbutil_list(void)
{
const struct usb_bus *bus;
for (bus = usb_get_busses(); bus; bus = bus->next) {
const struct usb_device *dev;
int busnum = atoi(bus->dirname);
printf("Devices on bus %03d:\n", busnum);
for (dev = bus->devices; dev; dev = dev->next) {
int devnum = atoi(dev->filename);
printf(" %03d:%03d %04x:%04x %s\n",
busnum, devnum,
dev->descriptor.idVendor,
dev->descriptor.idProduct,
device_help(dev));
}
}
}
struct usb_device *usbutil_find_by_id(int vendor, int product)
{
struct usb_bus *bus;
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev; dev = dev->next)
if (dev->descriptor.idVendor == vendor &&
dev->descriptor.idProduct == product)
return dev;
}
fprintf(stderr, "usbutil: unable to find a device matching "
"%04x:%04x\n", vendor, product);
return NULL;
}
struct usb_device *usbutil_find_by_loc(const char *loc)
{
char buf[64];
char *bus_text;
char *dev_text;
int target_bus;
int target_dev;
struct usb_bus *bus;
strncpy(buf, loc, sizeof(buf));
buf[sizeof(buf) - 1] = 0;
bus_text = strtok(buf, ":\t\r\n");
dev_text = strtok(NULL, ":\t\r\n");
if (!(bus_text && dev_text)) {
fprintf(stderr, "usbutil: location must be specified as "
"<bus>:<device>\n");
return NULL;
}
target_bus = atoi(bus_text);
target_dev = atoi(dev_text);
for (bus = usb_get_busses(); bus; bus = bus->next) {
struct usb_device *dev;
int busnum = atoi(bus->dirname);
if (busnum != target_bus)
continue;
for (dev = bus->devices; dev; dev = dev->next) {
int devnum = atoi(dev->filename);
if (devnum == target_dev)
return dev;
}
}
fprintf(stderr, "usbutil: unable to find %03d:%03d\n",
target_bus, target_dev);
return NULL;
}

33
usbutil.h Normal file
View File

@ -0,0 +1,33 @@
/* MSPDebug - debugging tool for MSP430 MCUs
* Copyright (C) 2009, 2010 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
*/
#ifndef USBUTIL_H_
#define USBUTIL_H_
#include <usb.h>
/* List all available USB devices. */
void usbutil_list(void);
/* Search for the first device matching the given Vendor:Product */
struct usb_device *usbutil_find_by_id(int vendor, int product);
/* Search for a device using a bus:dev location string */
struct usb_device *usbutil_find_by_loc(const char *loc);
#endif