Browse Source

USB add --usb options to limit USB device selection v0.1

nfactor-troky
Kano 12 years ago
parent
commit
3f50e878a2
  1. 53
      README
  2. 29
      cgminer.c
  3. 8
      miner.h
  4. 201
      usbutils.c
  5. 1
      usbutils.h

53
README

@ -221,10 +221,57 @@ SCRYPT only options:
See SCRYPT-README for more information regarding litecoin mining. 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 1' option
The '--usb-dump N' option with a value of N greater than 1 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 --scan-serial|-S <arg> Serial port to probe for Icarus mining device

29
cgminer.c

@ -136,7 +136,8 @@ bool opt_disable_pool;
char *opt_icarus_options = NULL; char *opt_icarus_options = NULL;
char *opt_icarus_timing = NULL; char *opt_icarus_timing = NULL;
bool opt_worktime; bool opt_worktime;
#ifdef HAVE_LIBUSB #ifdef USE_USBUTILS
char *opt_usb_select = NULL;
int opt_usbdump = -1; int opt_usbdump = -1;
#endif #endif
@ -169,7 +170,7 @@ static int new_threads;
static int start_devices; static int start_devices;
int hotplug_time = 5; int hotplug_time = 5;
#ifdef HAVE_LIBUSB #ifdef USE_USBUTILS
pthread_mutex_t cgusb_lock; pthread_mutex_t cgusb_lock;
#endif #endif
@ -823,6 +824,15 @@ static char *set_icarus_timing(const char *arg)
} }
#endif #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) static char *set_null(const char __maybe_unused *arg)
{ {
return NULL; return NULL;
@ -1154,7 +1164,10 @@ static struct opt_table opt_config_table[] = {
OPT_WITH_ARG("--user|-u", OPT_WITH_ARG("--user|-u",
set_user, NULL, NULL, set_user, NULL, NULL,
"Username for bitcoin JSON-RPC server"), "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", OPT_WITH_ARG("--usb-dump",
set_int_0_to_10, opt_show_intval, &opt_usbdump, set_int_0_to_10, opt_show_intval, &opt_usbdump,
opt_hidden), opt_hidden),
@ -4088,6 +4101,10 @@ void write_config(FILE *fcfg)
fprintf(fcfg, ",\n\"icarus-options\" : \"%s\"", json_escape(opt_icarus_options)); fprintf(fcfg, ",\n\"icarus-options\" : \"%s\"", json_escape(opt_icarus_options));
if (opt_icarus_timing) if (opt_icarus_timing)
fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", json_escape(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); fputs("\n}\n", fcfg);
json_escape_free(); json_escape_free();
@ -7031,7 +7048,6 @@ int main(int argc, char *argv[])
fflush(stderr); fflush(stderr);
quit(1, "libusb_init() failed"); quit(1, "libusb_init() failed");
} }
mutex_init(&cgusb_lock);
#endif #endif
mutex_init(&hash_lock); mutex_init(&hash_lock);
@ -7119,6 +7135,11 @@ int main(int argc, char *argv[])
if (argc != 1) if (argc != 1)
quit(1, "Unexpected extra commandline arguments"); quit(1, "Unexpected extra commandline arguments");
#ifdef USE_USBUTILS
mutex_init(&cgusb_lock);
usb_initialise();
#endif
if (!config_loaded) if (!config_loaded)
load_default_config(); load_default_config();

8
miner.h

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

201
usbutils.c

@ -9,6 +9,7 @@
#include "config.h" #include "config.h"
#include <ctype.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -146,6 +147,24 @@ extern struct device_drv icarus_drv;
#define STRBUFLEN 256 #define STRBUFLEN 256
static const char *BLANK = ""; 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; static bool stats_initialised = false;
struct cg_usb_stats_item { struct cg_usb_stats_item {
@ -894,6 +913,9 @@ static void release_cgpu(struct cgpu_info *cgpu)
if (cgpu->usbinfo.nodev) if (cgpu->usbinfo.nodev)
return; return;
total_count--;
drv_count[cgpu->drv->drv_id].count--;
cgpu->usbinfo.nodev = true; cgpu->usbinfo.nodev = true;
cgpu->usbinfo.nodev_count++; cgpu->usbinfo.nodev_count++;
gettimeofday(&(cgpu->usbinfo.last_nodev), NULL); gettimeofday(&(cgpu->usbinfo.last_nodev), NULL);
@ -903,6 +925,9 @@ static void release_cgpu(struct cgpu_info *cgpu)
for (i = 0; i < total_devices; i++) { for (i = 0; i < total_devices; i++) {
lookcgpu = get_devices(i); lookcgpu = get_devices(i);
if (lookcgpu != cgpu && lookcgpu->usbdev == cgusb) { if (lookcgpu != cgpu && lookcgpu->usbdev == cgusb) {
total_count--;
drv_count[lookcgpu->drv->drv_id].count--;
lookcgpu->usbinfo.nodev = true; lookcgpu->usbinfo.nodev = true;
lookcgpu->usbinfo.nodev_count++; lookcgpu->usbinfo.nodev_count++;
memcpy(&(lookcgpu->usbinfo.last_nodev), memcpy(&(lookcgpu->usbinfo.last_nodev),
@ -1121,7 +1146,9 @@ dame:
static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, struct usb_find_devices *look) static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, struct usb_find_devices *look)
{ {
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
int err; int bus_number, device_address;
int err, i;
bool ok;
err = libusb_get_device_descriptor(dev, &desc); err = libusb_get_device_descriptor(dev, &desc);
if (err) { if (err) {
@ -1136,6 +1163,27 @@ static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev,
return false; 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", applog(LOG_DEBUG, "%s looking for and found %s %04x:%04x",
drv->name, look->name, look->idVendor, look->idProduct); drv->name, look->name, look->idVendor, look->idProduct);
@ -1161,6 +1209,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) 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 #ifdef USE_BFLSC
if (drv->drv_id == DRIVER_BFLSC) if (drv->drv_id == DRIVER_BFLSC)
return usb_check_each(DRV_BFLSC, drv, dev); return usb_check_each(DRV_BFLSC, drv, dev);
@ -1190,7 +1245,19 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi
ssize_t count, i; ssize_t count, i;
struct usb_find_devices *found; 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); count = libusb_get_device_list(NULL, &list);
if (count < 0) { if (count < 0) {
@ -1202,6 +1269,18 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi
applog(LOG_DEBUG, "USB scan devices: found no devices"); applog(LOG_DEBUG, "USB scan devices: found no devices");
for (i = 0; i < count; i++) { 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]); found = usb_check(drv, list[i]);
if (found != NULL) { if (found != NULL) {
if (cgminer_usb_lock(drv, list[i]) == false) if (cgminer_usb_lock(drv, list[i]) == false)
@ -1209,6 +1288,10 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi
else { else {
if (!device_detect(list[i], found)) if (!device_detect(list[i], found))
cgminer_usb_unlock(drv, list[i]); cgminer_usb_unlock(drv, list[i]);
else {
total_count++;
drv_count[drv->drv_id].count++;
}
} }
} }
} }
@ -1240,8 +1323,6 @@ struct api_data *api_usb_stats(__maybe_unused int *count)
int device; int device;
int cmdseq; int cmdseq;
cgusb_check_init();
if (next_stat == 0) if (next_stat == 0)
return NULL; return NULL;
@ -1312,9 +1393,12 @@ static void newstats(struct cgpu_info *cgpu)
{ {
int i; int i;
mutex_lock(&cgusb_lock);
cgpu->usbinfo.usbstat = ++next_stat; cgpu->usbinfo.usbstat = ++next_stat;
mutex_unlock(&cgusb_lock);
usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat);
usb_stats[next_stat-1].name = cgpu->drv->name; usb_stats[next_stat-1].name = cgpu->drv->name;
usb_stats[next_stat-1].device_id = -1; 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); usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2);
@ -1584,3 +1668,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
int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds); 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); 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_cleanup();
void usb_initialise();
#define usb_read(cgpu, buf, bufsiz, read, cmd) \ #define usb_read(cgpu, buf, bufsiz, read, cmd) \
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false) _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false)

Loading…
Cancel
Save