|
|
|
@ -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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|