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 \ 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 \ 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) $(CC) $(LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
.c.o: .c.o:

32
main.c
View File

@ -29,6 +29,7 @@
#include "binfile.h" #include "binfile.h"
#include "stab.h" #include "stab.h"
#include "util.h" #include "util.h"
#include "usbutil.h"
#include "gdb.h" #include "gdb.h"
#include "rtools.h" #include "rtools.h"
#include "sym.h" #include "sym.h"
@ -121,6 +122,7 @@ static void store_io(void *user_data, uint16_t pc,
struct cmdline_args { struct cmdline_args {
const char *driver_name; const char *driver_name;
const char *serial_device; const char *serial_device;
const char *usb_device;
const char *fet_force_id; const char *fet_force_id;
int want_jtag; int want_jtag;
int no_rc; int no_rc;
@ -160,7 +162,7 @@ static device_t driver_open_rf2500(const struct cmdline_args *args)
return NULL; return NULL;
} }
trans = rf2500_open(); trans = rf2500_open(args->usb_device);
if (!trans) if (!trans)
return NULL; return NULL;
@ -174,7 +176,7 @@ static device_t driver_open_olimex(const struct cmdline_args *args)
if (args->serial_device) if (args->serial_device)
trans = uif_open(args->serial_device, 1); trans = uif_open(args->serial_device, 1);
else else
trans = olimex_open(); trans = olimex_open(args->usb_device);
if (!trans) if (!trans)
return NULL; return NULL;
@ -252,6 +254,8 @@ static void usage(const char *progname)
"\n" "\n"
" -d device\n" " -d device\n"
" Connect via the given tty device, rather than USB.\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" " -j\n"
" Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n" " Use JTAG, rather than Spy-Bi-Wire (UIF devices only).\n"
" -v voltage\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" " Show a list of devices supported by the FET driver.\n"
" --fet-force-id string\n" " --fet-force-id string\n"
" Override the device ID returned by the FET.\n" " Override the device ID returned by the FET.\n"
" --usb-list\n"
" Show a list of available USB devices.\n"
"\n" "\n"
"Most drivers connect by default via USB, unless told otherwise via the\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" "\n"
"If commands are given, they will be executed. Otherwise, an interactive\n" "If commands are given, they will be executed. Otherwise, an interactive\n"
"command reader is started.\n\n", "command reader is started.\n\n",
@ -335,16 +341,28 @@ static int parse_cmdline_args(int argc, char **argv,
{"help", 0, 0, 'H'}, {"help", 0, 0, 'H'},
{"fet-list", 0, 0, 'L'}, {"fet-list", 0, 0, 'L'},
{"fet-force-id", 1, 0, 'F'}, {"fet-force-id", 1, 0, 'F'},
{"usb-list", 0, 0, 'I'},
{NULL, 0, 0, 0} {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) longopts, NULL)) >= 0)
switch (opt) { switch (opt) {
case 'I':
usb_init();
usb_find_busses();
usb_find_devices();
usbutil_list();
exit(0);
case 'd': case 'd':
args->serial_device = optarg; args->serial_device = optarg;
break; break;
case 'U':
args->usb_device = optarg;
break;
case 'L': case 'L':
exit(list_devices()); exit(list_devices());
@ -373,6 +391,12 @@ static int parse_cmdline_args(int argc, char **argv,
return -1; 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) { if (optind >= argc) {
fprintf(stderr, "You need to specify a driver. Try --help for " fprintf(stderr, "You need to specify a driver. Try --help for "
"a list.\n"); "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. Specify that the driver should connect via a tty device rather than USB.
The supported connection methods vary depending on the driver. See the The supported connection methods vary depending on the driver. See the
section \fBDRIVERS\fR below for details. 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" .IP "\-n"
Do not process the startup file (~/.mspdebug). Do not process the startup file (~/.mspdebug).
.IP "\-\-help" .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 When using a FET device, force the connected chip to be recognised by
MSPDebug as one of the given type during initialization. This overrides MSPDebug as one of the given type during initialization. This overrides
the device ID returned by the FET. the device ID returned by the FET.
.IP "\-\-usb\-list"
List available USB devices and exit.
.SH DRIVERS .SH DRIVERS
A driver name must be specified on the command line for MSPDebug to A driver name must be specified on the command line for MSPDebug to
connect to. Valid driver names are listed here. connect to. Valid driver names are listed here.

View File

@ -23,6 +23,7 @@
#include "olimex.h" #include "olimex.h"
#include "util.h" #include "util.h"
#include "usbutil.h"
struct olimex_transport { struct olimex_transport {
struct transport base; struct transport base;
@ -190,10 +191,11 @@ static void usbtr_destroy(transport_t tr_base)
free(tr); free(tr);
} }
transport_t olimex_open(void) transport_t olimex_open(const char *devpath)
{ {
struct olimex_transport *tr = malloc(sizeof(*tr)); struct olimex_transport *tr = malloc(sizeof(*tr));
struct usb_bus *bus; struct usb_device *dev;
char buf[64];
if (!tr) { if (!tr) {
perror(__FILE__": can't allocate memory"); perror(__FILE__": can't allocate memory");
@ -208,26 +210,25 @@ transport_t olimex_open(void)
usb_find_busses(); usb_find_busses();
usb_find_devices(); usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) { if (devpath)
struct usb_device *dev; 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) {
if (dev->descriptor.idVendor == USB_FET_VENDOR && free(tr);
dev->descriptor.idProduct == USB_FET_PRODUCT && return NULL;
!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;
}
}
} }
fprintf(stderr, __FILE__": no devices could be found\n"); if (open_device(tr, dev) < 0) {
free(tr); fprintf(stderr, __FILE__ ": failed to open Olimex device\n");
return NULL; 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 /* Search the USB bus for the first Olimex MSP-JTAG-TINY, and
* initialize it. If successful, 0 is returned and the fet_* functions * initialize it. If successful, 0 is returned and the fet_* functions
* are ready for use. If an error occurs, -1 is returned. * 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 #endif

View File

@ -22,6 +22,7 @@
#include "rf2500.h" #include "rf2500.h"
#include "util.h" #include "util.h"
#include "usbutil.h"
struct rf2500_transport { struct rf2500_transport {
struct transport base; struct transport base;
@ -177,10 +178,11 @@ static void usbtr_destroy(transport_t tr_base)
free(tr); free(tr);
} }
transport_t rf2500_open(void) transport_t rf2500_open(const char *devpath)
{ {
struct rf2500_transport *tr = malloc(sizeof(*tr)); struct rf2500_transport *tr = malloc(sizeof(*tr));
struct usb_bus *bus; struct usb_device *dev;
char buf[64];
if (!tr) { if (!tr) {
perror("rf2500: can't allocate memory"); perror("rf2500: can't allocate memory");
@ -195,26 +197,25 @@ transport_t rf2500_open(void)
usb_find_busses(); usb_find_busses();
usb_find_devices(); usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) { if (devpath)
struct usb_device *dev; 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) {
if (dev->descriptor.idVendor == USB_FET_VENDOR && free(tr);
dev->descriptor.idProduct == USB_FET_PRODUCT && return NULL;
!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;
}
}
} }
fprintf(stderr, "rf2500: no devices could be found\n"); if (open_device(tr, dev) < 0) {
free(tr); fprintf(stderr, "rf2500: failed to open RF2500 device\n");
return NULL; 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 /* 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. * successful, 0 is returned and the fet_* functions are ready for use.
* If an error occurs, -1 is returned. * 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 #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