Browse Source

Merge pull request #403 from kanoi/bflsc

USB add --usb options to limit USB device selection v0.1 + --usb-dump display brief dump if value = 0
nfactor-troky
Con Kolivas 12 years ago
parent
commit
ffc8681f91
  1. 53
      README
  2. 29
      cgminer.c
  3. 8
      miner.h
  4. 240
      usbutils.c
  5. 1
      usbutils.h

53
README

@ -224,10 +224,57 @@ SCRYPT only options: @@ -224,10 +224,57 @@ SCRYPT only options:
See SCRYPT-README for more information regarding litecoin mining.
FPGA mining boards (BitForce, Icarus, ModMiner, Ztex) only options:
ASIC and FPGA mining boards (BFL ASIC, BitForce, Icarus, ModMiner, Ztex)
only options:
Cgminer will automatically find all of your BFL ASIC, BitForce FPGAs,
ModMiner FPGAs or Ztex FPGAs
The --usb option can restrict how many BFL ASIC, BitForce FPGAs or
ModMiner FPGAs it finds:
--usb 1:2,1:3,1:4,1:*
or
--usb BAS:1,BFL:1,MMQ:0
or
--usb :10
You can only use one of the above 3
The first version
--usb 1:2,1:3,1:4,1:*
allows you to select which devices to mine on with a list of USB
bus_number:device_address
All other USB devices will be ignored
Hotplug will also only look at the devices matching the list specified and
find nothing new if they are all in use
You can specify just the USB bus_number to find all devices like 1:*
which means any devices on USB bus_number 1
This is useful if you unplug a device then plug it back in the same port,
it usually reappears with the same bus_number but a different device_address
You can see the list of USB devices on linux with 'sudo lsusb'
Cgminer will list the USB devices with the '--usb-dump 0' option
The '--usb-dump N' option with a value of N greater than 0 will dump a lot
of details about each USB device
The second version
--usb BAS:1,BFL:1,MMQ:0
allows you to specify how many devices to choose based on each device
driver cgminer has - there are currently 3 USB drivers: BAS, BFL & MMQ
N.B. you can only specify which device driver to limit, not the type of
each device, e.g. with BAS:n you can limit how many BFL ASIC devices will
be checked, but you cannot limit the number of each type of BFL ASIC
Also note that the MMQ count is the number of MMQ backplanes you have
not the number of MMQ FPGAs
The third version
--usb :10
means only use a maximum of 10 devices of any supported USB devices
Once cgminer has 10 devices it will not configure any more and hotplug will
not scan for any more
If one of the 10 devices stops working, hotplug - if enabled, as is default
- will scan normally again until it has 10 devices
cgminer will automatically find your ModMiner, BitForce or Ztex FPGAs
independent of the --scan-serial options specified below
--scan-serial|-S <arg> Serial port to probe for Icarus mining device

29
cgminer.c

@ -136,7 +136,8 @@ bool opt_disable_pool; @@ -136,7 +136,8 @@ bool opt_disable_pool;
char *opt_icarus_options = NULL;
char *opt_icarus_timing = NULL;
bool opt_worktime;
#ifdef HAVE_LIBUSB
#ifdef USE_USBUTILS
char *opt_usb_select = NULL;
int opt_usbdump = -1;
#endif
@ -169,7 +170,7 @@ static int new_threads; @@ -169,7 +170,7 @@ static int new_threads;
static int start_devices;
int hotplug_time = 5;
#ifdef HAVE_LIBUSB
#ifdef USE_USBUTILS
pthread_mutex_t cgusb_lock;
#endif
@ -826,6 +827,15 @@ static char *set_icarus_timing(const char *arg) @@ -826,6 +827,15 @@ static char *set_icarus_timing(const char *arg)
}
#endif
#ifdef USE_USBUTILS
static char *set_usb_select(const char *arg)
{
opt_set_charp(arg, &opt_usb_select);
return NULL;
}
#endif
static char *set_null(const char __maybe_unused *arg)
{
return NULL;
@ -1157,7 +1167,10 @@ static struct opt_table opt_config_table[] = { @@ -1157,7 +1167,10 @@ static struct opt_table opt_config_table[] = {
OPT_WITH_ARG("--user|-u",
set_user, NULL, NULL,
"Username for bitcoin JSON-RPC server"),
#ifdef HAVE_LIBUSB
#ifdef USE_USBUTILS
OPT_WITH_ARG("--usb",
set_usb_select, NULL, NULL,
"USB device selection"),
OPT_WITH_ARG("--usb-dump",
set_int_0_to_10, opt_show_intval, &opt_usbdump,
opt_hidden),
@ -4087,6 +4100,10 @@ void write_config(FILE *fcfg) @@ -4087,6 +4100,10 @@ void write_config(FILE *fcfg)
fprintf(fcfg, ",\n\"icarus-options\" : \"%s\"", json_escape(opt_icarus_options));
if (opt_icarus_timing)
fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", json_escape(opt_icarus_timing));
#ifdef USE_USBUTILS
if (opt_usb_select)
fprintf(fcfg, ",\n\"usb\" : \"%s\"", json_escape(opt_usb_select));
#endif
fputs("\n}\n", fcfg);
json_escape_free();
@ -7034,7 +7051,9 @@ int main(int argc, char *argv[]) @@ -7034,7 +7051,9 @@ int main(int argc, char *argv[])
fflush(stderr);
quit(1, "libusb_init() failed");
}
#ifdef USE_USBUTILS
mutex_init(&cgusb_lock);
#endif
#endif
mutex_init(&hash_lock);
@ -7170,6 +7189,10 @@ int main(int argc, char *argv[]) @@ -7170,6 +7189,10 @@ int main(int argc, char *argv[])
if (want_per_device_stats)
opt_log_output = true;
#ifdef USE_USBUTILS
usb_initialise();
#endif
#ifdef WANT_CPUMINE
#ifdef USE_SCRYPT
if (opt_scrypt)

8
miner.h

@ -197,13 +197,14 @@ static inline int fsync (int fd) @@ -197,13 +197,14 @@ static inline int fsync (int fd)
#endif
enum drv_driver {
DRIVER_OPENCL,
DRIVER_OPENCL = 0,
DRIVER_ICARUS,
DRIVER_BITFORCE,
DRIVER_MODMINER,
DRIVER_ZTEX,
DRIVER_CPU,
DRIVER_BFLSC,
DRIVER_MAX
};
enum alive {
@ -777,7 +778,8 @@ extern bool opt_restart; @@ -777,7 +778,8 @@ extern bool opt_restart;
extern char *opt_icarus_options;
extern char *opt_icarus_timing;
extern bool opt_worktime;
#ifdef HAVE_LIBUSB
#ifdef USE_USBUTILS
extern char *opt_usb_select;
extern int opt_usbdump;
#endif
#ifdef USE_BITFORCE
@ -810,7 +812,7 @@ extern int opt_queue; @@ -810,7 +812,7 @@ extern int opt_queue;
extern int opt_scantime;
extern int opt_expiry;
#ifdef HAVE_LIBUSB
#ifdef USE_USBUTILS
extern pthread_mutex_t cgusb_lock;
#endif

240
usbutils.c

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
#include "config.h"
#include <ctype.h>
#include <stdint.h>
#include <stdbool.h>
@ -146,6 +147,24 @@ extern struct device_drv icarus_drv; @@ -146,6 +147,24 @@ extern struct device_drv icarus_drv;
#define STRBUFLEN 256
static const char *BLANK = "";
// For device limits by driver
static struct driver_count {
uint32_t count;
uint32_t limit;
} drv_count[DRIVER_MAX];
// For device limits by list of bus/dev
static struct usb_busdev {
int bus_number;
int device_address;
} *busdev;
static int busdev_count = 0;
// Total device limit
static int total_count = 0;
static int total_limit = 999999;
static bool stats_initialised = false;
struct cg_usb_stats_item {
@ -395,6 +414,8 @@ static bool setgetdes(ssize_t count, libusb_device *dev, struct libusb_device_ha @@ -395,6 +414,8 @@ static bool setgetdes(ssize_t count, libusb_device *dev, struct libusb_device_ha
static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off, size_t *len)
{
struct libusb_device_descriptor desc;
uint8_t bus_number;
uint8_t device_address;
struct libusb_device_handle *handle;
struct libusb_config_descriptor *config;
const struct libusb_interface_descriptor *idesc;
@ -413,16 +434,26 @@ static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off, @@ -413,16 +434,26 @@ static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off,
return;
}
sprintf(tmp, EOL ".USB dev %d: Device Descriptor:" EOL "\tLength: %d" EOL
bus_number = libusb_get_bus_number(dev);
device_address = libusb_get_device_address(dev);
if (opt_usbdump == 0) {
sprintf(tmp, EOL ".USB dev %d: Bus %d Device %d ID: %04x:%04x",
(int)count, (int)bus_number, (int)device_address,
desc.idVendor, desc.idProduct);
} else {
sprintf(tmp, EOL ".USB dev %d: Bus %d Device %d Device Descriptor:" EOL "\tLength: %d" EOL
"\tDescriptor Type: %s" EOL "\tUSB: %04x" EOL "\tDeviceClass: %d" EOL
"\tDeviceSubClass: %d" EOL "\tDeviceProtocol: %d" EOL "\tMaxPacketSize0: %d" EOL
"\tidVendor: %04x" EOL "\tidProduct: %04x" EOL "\tDeviceRelease: %x" EOL
"\tNumConfigurations: %d",
(int)count, (int)(desc.bLength), destype(desc.bDescriptorType),
(int)count, (int)bus_number, (int)device_address,
(int)(desc.bLength), destype(desc.bDescriptorType),
desc.bcdUSB, (int)(desc.bDeviceClass), (int)(desc.bDeviceSubClass),
(int)(desc.bDeviceProtocol), (int)(desc.bMaxPacketSize0),
desc.idVendor, desc.idProduct, desc.bcdDevice,
(int)(desc.bNumConfigurations));
}
append(buf, tmp, off, len);
err = libusb_open(dev, &handle);
@ -432,6 +463,21 @@ static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off, @@ -432,6 +463,21 @@ static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off,
return;
}
err = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, man, STRBUFLEN);
if (err < 0)
sprintf((char *)man, "** err(%d)", err);
err = libusb_get_string_descriptor_ascii(handle, desc.iProduct, prod, STRBUFLEN);
if (err < 0)
sprintf((char *)prod, "** err(%d)", err);
if (opt_usbdump == 0) {
libusb_close(handle);
sprintf(tmp, EOL " Manufacturer: '%s'" EOL " Product: '%s'", man, prod);
append(buf, tmp, off, len);
return;
}
if (libusb_kernel_driver_active(handle, 0) == 1) {
sprintf(tmp, EOL " * dev %d: kernel attached", (int)count);
append(buf, tmp, off, len);
@ -497,14 +543,6 @@ static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off, @@ -497,14 +543,6 @@ static void usb_full(ssize_t count, libusb_device *dev, char **buf, size_t *off,
libusb_free_config_descriptor(config);
config = NULL;
err = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, man, STRBUFLEN);
if (err < 0)
sprintf((char *)man, "** err(%d)", err);
err = libusb_get_string_descriptor_ascii(handle, desc.iProduct, prod, STRBUFLEN);
if (err < 0)
sprintf((char *)prod, "** err(%d)", err);
err = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, ser, STRBUFLEN);
if (err < 0)
sprintf((char *)ser, "** err(%d)", err);
@ -894,6 +932,9 @@ static void release_cgpu(struct cgpu_info *cgpu) @@ -894,6 +932,9 @@ static void release_cgpu(struct cgpu_info *cgpu)
if (cgpu->usbinfo.nodev)
return;
total_count--;
drv_count[cgpu->drv->drv_id].count--;
cgpu->usbinfo.nodev = true;
cgpu->usbinfo.nodev_count++;
gettimeofday(&(cgpu->usbinfo.last_nodev), NULL);
@ -903,6 +944,9 @@ static void release_cgpu(struct cgpu_info *cgpu) @@ -903,6 +944,9 @@ static void release_cgpu(struct cgpu_info *cgpu)
for (i = 0; i < total_devices; i++) {
lookcgpu = get_devices(i);
if (lookcgpu != cgpu && lookcgpu->usbdev == cgusb) {
total_count--;
drv_count[lookcgpu->drv->drv_id].count--;
lookcgpu->usbinfo.nodev = true;
lookcgpu->usbinfo.nodev_count++;
memcpy(&(lookcgpu->usbinfo.last_nodev),
@ -1121,7 +1165,9 @@ dame: @@ -1121,7 +1165,9 @@ dame:
static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, struct usb_find_devices *look)
{
struct libusb_device_descriptor desc;
int err;
int bus_number, device_address;
int err, i;
bool ok;
err = libusb_get_device_descriptor(dev, &desc);
if (err) {
@ -1136,6 +1182,27 @@ static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, @@ -1136,6 +1182,27 @@ static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev,
return false;
}
if (busdev_count > 0) {
bus_number = (int)libusb_get_bus_number(dev);
device_address = (int)libusb_get_device_address(dev);
ok = false;
for (i = 0; i < busdev_count; i++) {
if (bus_number == busdev[i].bus_number) {
if (busdev[i].device_address == -1 ||
device_address == busdev[i].device_address) {
ok = true;
break;
}
}
}
if (!ok) {
applog(LOG_DEBUG, "%s rejected %s %04x:%04x with bus:dev (%d:%d)",
drv->name, look->name, look->idVendor, look->idProduct,
bus_number, device_address);
return false;
}
}
applog(LOG_DEBUG, "%s looking for and found %s %04x:%04x",
drv->name, look->name, look->idVendor, look->idProduct);
@ -1161,6 +1228,13 @@ static struct usb_find_devices *usb_check_each(int drvnum, struct device_drv *dr @@ -1161,6 +1228,13 @@ static struct usb_find_devices *usb_check_each(int drvnum, struct device_drv *dr
static struct usb_find_devices *usb_check(__maybe_unused struct device_drv *drv, __maybe_unused struct libusb_device *dev)
{
if (drv_count[drv->drv_id].count >= drv_count[drv->drv_id].limit) {
applog(LOG_DEBUG,
"USB scan devices3: %s limit %d reached",
drv->dname, drv_count[drv->drv_id].limit);
return NULL;
}
#ifdef USE_BFLSC
if (drv->drv_id == DRIVER_BFLSC)
return usb_check_each(DRV_BFLSC, drv, dev);
@ -1190,7 +1264,19 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi @@ -1190,7 +1264,19 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi
ssize_t count, i;
struct usb_find_devices *found;
cgusb_check_init();
applog(LOG_DEBUG, "USB scan devices: checking for %s devices", drv->name);
if (total_count >= total_limit) {
applog(LOG_DEBUG, "USB scan devices: total limit %d reached", total_limit);
return;
}
if (drv_count[drv->drv_id].count >= drv_count[drv->drv_id].limit) {
applog(LOG_DEBUG,
"USB scan devices: %s limit %d reached",
drv->dname, drv_count[drv->drv_id].limit);
return;
}
count = libusb_get_device_list(NULL, &list);
if (count < 0) {
@ -1202,6 +1288,18 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi @@ -1202,6 +1288,18 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi
applog(LOG_DEBUG, "USB scan devices: found no devices");
for (i = 0; i < count; i++) {
if (total_count >= total_limit) {
applog(LOG_DEBUG, "USB scan devices2: total limit %d reached", total_limit);
break;
}
if (drv_count[drv->drv_id].count >= drv_count[drv->drv_id].limit) {
applog(LOG_DEBUG,
"USB scan devices2: %s limit %d reached",
drv->dname, drv_count[drv->drv_id].limit);
break;
}
found = usb_check(drv, list[i]);
if (found != NULL) {
if (cgminer_usb_lock(drv, list[i]) == false)
@ -1209,6 +1307,10 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi @@ -1209,6 +1307,10 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi
else {
if (!device_detect(list[i], found))
cgminer_usb_unlock(drv, list[i]);
else {
total_count++;
drv_count[drv->drv_id].count++;
}
}
}
}
@ -1240,8 +1342,6 @@ struct api_data *api_usb_stats(__maybe_unused int *count) @@ -1240,8 +1342,6 @@ struct api_data *api_usb_stats(__maybe_unused int *count)
int device;
int cmdseq;
cgusb_check_init();
if (next_stat == 0)
return NULL;
@ -1312,9 +1412,12 @@ static void newstats(struct cgpu_info *cgpu) @@ -1312,9 +1412,12 @@ static void newstats(struct cgpu_info *cgpu)
{
int i;
mutex_lock(&cgusb_lock);
cgpu->usbinfo.usbstat = ++next_stat;
mutex_unlock(&cgusb_lock);
usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat);
usb_stats[next_stat-1].name = cgpu->drv->name;
usb_stats[next_stat-1].device_id = -1;
usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2);
@ -1584,3 +1687,112 @@ void usb_cleanup() @@ -1584,3 +1687,112 @@ void usb_cleanup()
}
}
}
void usb_initialise()
{
char *fre, *ptr, *comma, *colon;
int bus, dev, lim, i;
bool found;
for (i = 0; i < DRIVER_MAX; i++) {
drv_count[i].count = 0;
drv_count[i].limit = 999999;
}
cgusb_check_init();
if (opt_usb_select && *opt_usb_select) {
// Absolute device limit
if (*opt_usb_select == ':') {
total_limit = atoi(opt_usb_select+1);
if (total_limit < 0)
quit(1, "Invalid --usb total limit");
// Comma list of bus:dev devices to match
} else if (isdigit(*opt_usb_select)) {
fre = ptr = strdup(opt_usb_select);
do {
comma = strchr(ptr, ',');
if (comma)
*(comma++) = '\0';
colon = strchr(ptr, ':');
if (!colon)
quit(1, "Invalid --usb bus:dev missing ':'");
*(colon++) = '\0';
if (!isdigit(*ptr))
quit(1, "Invalid --usb bus:dev - bus must be a number");
if (!isdigit(*colon) && *colon != '*')
quit(1, "Invalid --usb bus:dev - dev must be a number or '*'");
bus = atoi(ptr);
if (bus <= 0)
quit(1, "Invalid --usb bus:dev - bus must be > 0");
if (!colon == '*')
dev = -1;
else {
dev = atoi(colon);
if (dev <= 0)
quit(1, "Invalid --usb bus:dev - dev must be > 0 or '*'");
}
busdev = realloc(busdev, sizeof(*busdev) * (++busdev_count));
busdev[busdev_count-1].bus_number = bus;
busdev[busdev_count-1].device_address = dev;
ptr = comma;
} while (ptr);
free(fre);
// Comma list of DRV:limit
} else {
fre = ptr = strdup(opt_usb_select);
do {
comma = strchr(ptr, ',');
if (comma)
*(comma++) = '\0';
colon = strchr(ptr, ':');
if (!colon)
quit(1, "Invalid --usb DRV:limit missing ':'");
*(colon++) = '\0';
if (!isdigit(*colon))
quit(1, "Invalid --usb DRV:limit - limit must be a number");
lim = atoi(colon);
if (lim < 0)
quit(1, "Invalid --usb DRV:limit - limit must be >= 0");
found = false;
#ifdef USE_BFLSC
if (strcasecmp(ptr, bflsc_drv.name) == 0) {
drv_count[bflsrc_drv.drv_id].limit = lim;
found = true;
}
#endif
#ifdef USE_BITFORCE
if (!found && strcasecmp(ptr, bitforce_drv.name) == 0) {
drv_count[bitforce_drv.drv_id].limit = lim;
found = true;
}
#endif
#ifdef USE_MODMINER
if (!found && strcasecmp(ptr, modminer_drv.name) == 0) {
drv_count[modminer_drv.drv_id].limit = lim;
found = true;
}
#endif
if (!found)
quit(1, "Invalid --usb DRV:limit - unknown DRV='%s'", ptr);
ptr = comma;
} while (ptr);
free(fre);
}
}
}

1
usbutils.h

@ -138,6 +138,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro @@ -138,6 +138,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds);
int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd);
void usb_cleanup();
void usb_initialise();
#define usb_read(cgpu, buf, bufsiz, read, cmd) \
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false)

Loading…
Cancel
Save