|
|
|
@ -1379,7 +1379,8 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
@@ -1379,7 +1379,8 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
|
|
|
|
|
if (cgusb->prod_string && cgusb->prod_string != BLANK) |
|
|
|
|
free(cgusb->prod_string); |
|
|
|
|
|
|
|
|
|
free(cgusb->descriptor); |
|
|
|
|
if (cgusb->descriptor) |
|
|
|
|
free(cgusb->descriptor); |
|
|
|
|
|
|
|
|
|
free(cgusb->found); |
|
|
|
|
|
|
|
|
@ -1391,7 +1392,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
@@ -1391,7 +1392,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _usb_uninit(struct cgpu_info *cgpu) |
|
|
|
|
static void _usb_uninit(struct cgpu_info *cgpu) |
|
|
|
|
{ |
|
|
|
|
applog(LOG_DEBUG, "USB uninit %s%i", |
|
|
|
|
cgpu->drv->name, cgpu->device_id); |
|
|
|
@ -1400,18 +1401,12 @@ void _usb_uninit(struct cgpu_info *cgpu)
@@ -1400,18 +1401,12 @@ void _usb_uninit(struct cgpu_info *cgpu)
|
|
|
|
|
// if release_cgpu() was called due to a USB NODEV(err)
|
|
|
|
|
if (!cgpu->usbdev) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (cgpu->usbdev->handle) { |
|
|
|
|
int ifinfo = 0; |
|
|
|
|
while (cgpu->usbdev->claimed > 0) { |
|
|
|
|
libusb_release_interface(cgpu->usbdev->handle, |
|
|
|
|
cgpu->usbdev->found->intinfos[ifinfo].interface); |
|
|
|
|
ifinfo++; |
|
|
|
|
cgpu->usbdev->claimed--; |
|
|
|
|
} |
|
|
|
|
libusb_release_interface(cgpu->usbdev->handle, USBIF(cgpu->usbdev)); |
|
|
|
|
cg_wlock(&cgusb_fd_lock); |
|
|
|
|
libusb_close(cgpu->usbdev->handle); |
|
|
|
|
cgpu->usbdev->handle = NULL; |
|
|
|
|
cgpu->usbdev->claimed = 0; |
|
|
|
|
cg_wunlock(&cgusb_fd_lock); |
|
|
|
|
} |
|
|
|
|
cgpu->usbdev = free_cgusb(cgpu->usbdev); |
|
|
|
@ -1474,11 +1469,16 @@ static void release_cgpu(struct cgpu_info *cgpu)
@@ -1474,11 +1469,16 @@ static void release_cgpu(struct cgpu_info *cgpu)
|
|
|
|
|
cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Currently only used by MMQ
|
|
|
|
|
// Used by MMQ - use the same usbdev thus locking is across all 4 related devices
|
|
|
|
|
// since they must use the same USB handle since they use the same interface
|
|
|
|
|
struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig) |
|
|
|
|
{ |
|
|
|
|
struct cgpu_info *copy = calloc(1, sizeof(*copy)); |
|
|
|
|
struct cgpu_info *copy; |
|
|
|
|
int pstate; |
|
|
|
|
|
|
|
|
|
DEVLOCK(orig, pstate); |
|
|
|
|
|
|
|
|
|
copy = calloc(1, sizeof(*copy)); |
|
|
|
|
if (unlikely(!copy)) |
|
|
|
|
quit(1, "Failed to calloc cgpu for %s in usb_copy_cgpu", orig->drv->dname); |
|
|
|
|
|
|
|
|
@ -1495,6 +1495,70 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
@@ -1495,6 +1495,70 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
|
|
|
|
|
|
|
|
|
|
copy->usbinfo.devlock = orig->usbinfo.devlock; |
|
|
|
|
|
|
|
|
|
DEVUNLOCK(orig, pstate); |
|
|
|
|
|
|
|
|
|
return copy; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Used by CMR - use a different usbdev - since they must use a different
|
|
|
|
|
// USB handle due to using different interfaces (libusb requirement)
|
|
|
|
|
static struct cgpu_info *usb_dup_cgpu(struct cgpu_info *orig, int intinfo) |
|
|
|
|
{ |
|
|
|
|
struct cgpu_info *copy; |
|
|
|
|
|
|
|
|
|
copy = calloc(1, sizeof(*copy)); |
|
|
|
|
if (unlikely(!copy)) |
|
|
|
|
quit(1, "Failed to calloc cgpu for %s in usb_dup_cgpu", orig->drv->dname); |
|
|
|
|
|
|
|
|
|
copy->name = orig->name; |
|
|
|
|
copy->drv = copy_drv(orig->drv); |
|
|
|
|
copy->deven = orig->deven; |
|
|
|
|
copy->threads = orig->threads; |
|
|
|
|
|
|
|
|
|
if (orig->usbdev) { |
|
|
|
|
copy->usbdev = calloc(1, sizeof(*(copy->usbdev))); |
|
|
|
|
if (unlikely(!copy->usbdev)) |
|
|
|
|
quit(1, "Failed to calloc usbdev for %s in usb_dup_cgpu", orig->drv->dname); |
|
|
|
|
|
|
|
|
|
copy->usbdev->found = malloc(sizeof(*(copy->usbdev->found))); |
|
|
|
|
if (unlikely(!copy->usbdev->found)) |
|
|
|
|
quit(1, "Failed to malloc found for %s in usb_dup_cgpu", orig->drv->dname); |
|
|
|
|
memcpy(copy->usbdev->found, orig->usbdev->found, sizeof(*(copy->usbdev->found))); |
|
|
|
|
|
|
|
|
|
copy->usbdev->found->which_intinfo = intinfo; |
|
|
|
|
|
|
|
|
|
copy->usbdev->descriptor = NULL; // don't need it
|
|
|
|
|
copy->usbdev->usb_type = orig->usbdev->usb_type; |
|
|
|
|
copy->usbdev->ident = orig->usbdev->ident; |
|
|
|
|
copy->usbdev->usbver = orig->usbdev->usbver; |
|
|
|
|
copy->usbdev->cps = orig->usbdev->cps; |
|
|
|
|
copy->usbdev->usecps = orig->usbdev->usecps; |
|
|
|
|
if (orig->usbdev->prod_string == BLANK) |
|
|
|
|
copy->usbdev->prod_string = (char *)BLANK; |
|
|
|
|
else |
|
|
|
|
copy->usbdev->prod_string = strdup(orig->usbdev->prod_string); |
|
|
|
|
if (orig->usbdev->manuf_string == BLANK) |
|
|
|
|
copy->usbdev->manuf_string = (char *)BLANK; |
|
|
|
|
else |
|
|
|
|
copy->usbdev->manuf_string = strdup(orig->usbdev->manuf_string); |
|
|
|
|
if (orig->usbdev->serial_string == BLANK) |
|
|
|
|
copy->usbdev->serial_string = (char *)BLANK; |
|
|
|
|
else |
|
|
|
|
copy->usbdev->serial_string = strdup(orig->usbdev->serial_string); |
|
|
|
|
copy->usbdev->fwVersion = orig->usbdev->fwVersion; |
|
|
|
|
copy->usbdev->interfaceVersion = orig->usbdev->interfaceVersion; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
memcpy(&(copy->usbinfo), &(orig->usbinfo), sizeof(copy->usbinfo)); |
|
|
|
|
|
|
|
|
|
copy->usbinfo.nodev = (copy->usbdev == NULL); |
|
|
|
|
|
|
|
|
|
copy->usbinfo.devlock = calloc(1, sizeof(*(copy->usbinfo.devlock))); |
|
|
|
|
if (unlikely(!copy->usbinfo.devlock)) |
|
|
|
|
quit(1, "Failed to calloc devlock for %s in usb_dup_cgpu", orig->drv->dname); |
|
|
|
|
|
|
|
|
|
rwlock_init(copy->usbinfo.devlock); |
|
|
|
|
|
|
|
|
|
return copy; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1616,22 +1680,18 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1616,22 +1680,18 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef WIN32 |
|
|
|
|
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) { |
|
|
|
|
int interface = found->intinfos[ifinfo].interface; |
|
|
|
|
|
|
|
|
|
if (libusb_kernel_driver_active(cgusb->handle, interface) == 1) { |
|
|
|
|
applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); |
|
|
|
|
err = libusb_detach_kernel_driver(cgusb->handle, interface); |
|
|
|
|
if (err == 0) { |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init, kernel detached interface %d successfully %s", |
|
|
|
|
interface, devstr); |
|
|
|
|
} else { |
|
|
|
|
applog(LOG_WARNING, |
|
|
|
|
"USB init, kernel detach interface %d failed, err %d in use? %s", |
|
|
|
|
interface, err, devstr); |
|
|
|
|
goto cldame; |
|
|
|
|
} |
|
|
|
|
if (libusb_kernel_driver_active(cgusb->handle, FOUNDIF(found)) == 1) { |
|
|
|
|
applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); |
|
|
|
|
err = libusb_detach_kernel_driver(cgusb->handle, FOUNDIF(found)); |
|
|
|
|
if (err == 0) { |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init, kernel detached interface %d successfully %s", |
|
|
|
|
FOUNDIF(found), devstr); |
|
|
|
|
} else { |
|
|
|
|
applog(LOG_WARNING, |
|
|
|
|
"USB init, kernel detach interface %d failed, err %d in use? %s", |
|
|
|
|
FOUNDIF(found), err, devstr); |
|
|
|
|
goto cldame; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
@ -1754,25 +1814,20 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1754,25 +1814,20 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
|
|
|
|
|
goto cldame; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cgusb->claimed = 0; |
|
|
|
|
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) { |
|
|
|
|
int interface = found->intinfos[ifinfo].interface; |
|
|
|
|
err = libusb_claim_interface(cgusb->handle, interface); |
|
|
|
|
if (err) { |
|
|
|
|
switch(err) { |
|
|
|
|
case LIBUSB_ERROR_BUSY: |
|
|
|
|
applog(LOG_WARNING, |
|
|
|
|
"USB init, claim interface %d in use %s", |
|
|
|
|
interface, devstr); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init, claim interface %d failed, err %d %s", |
|
|
|
|
interface, err, devstr); |
|
|
|
|
} |
|
|
|
|
goto reldame; |
|
|
|
|
err = libusb_claim_interface(cgusb->handle, FOUNDIF(found)); |
|
|
|
|
if (err) { |
|
|
|
|
switch(err) { |
|
|
|
|
case LIBUSB_ERROR_BUSY: |
|
|
|
|
applog(LOG_WARNING, |
|
|
|
|
"USB init, claim interface %d in use %s", |
|
|
|
|
FOUNDIF(found), devstr); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init, claim interface %d failed, err %d %s", |
|
|
|
|
FOUNDIF(found), err, devstr); |
|
|
|
|
} |
|
|
|
|
cgusb->claimed++; |
|
|
|
|
goto reldame; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cfg = -1; |
|
|
|
@ -1839,19 +1894,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1839,19 +1894,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
|
|
|
|
|
|
|
|
|
|
reldame: |
|
|
|
|
|
|
|
|
|
ifinfo = 0; |
|
|
|
|
while (cgusb->claimed > 0) { |
|
|
|
|
libusb_release_interface(cgusb->handle, found->intinfos[ifinfo].interface); |
|
|
|
|
ifinfo++; |
|
|
|
|
cgusb->claimed--; |
|
|
|
|
} |
|
|
|
|
libusb_release_interface(cgusb->handle, FOUNDIF(found)); |
|
|
|
|
|
|
|
|
|
cldame: |
|
|
|
|
|
|
|
|
|
cg_wlock(&cgusb_fd_lock); |
|
|
|
|
libusb_close(cgusb->handle); |
|
|
|
|
cgusb->handle = NULL; |
|
|
|
|
cgusb->claimed = 0; |
|
|
|
|
cg_wunlock(&cgusb_fd_lock); |
|
|
|
|
|
|
|
|
|
dame: |
|
|
|
@ -1867,6 +1916,144 @@ out_unlock:
@@ -1867,6 +1916,144 @@ out_unlock:
|
|
|
|
|
return bad; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// To get the extra interfaces on a multi interface device
|
|
|
|
|
struct cgpu_info *usb_init_intinfo(struct cgpu_info *orig, int intinfo) |
|
|
|
|
{ |
|
|
|
|
struct usb_find_devices *found; |
|
|
|
|
struct libusb_device *dev; |
|
|
|
|
struct cgpu_info *copy = NULL; |
|
|
|
|
char msgstr[STRBUFLEN+1]; |
|
|
|
|
char devstr[STRBUFLEN+1]; |
|
|
|
|
char devpath[32]; |
|
|
|
|
int err, pstate; |
|
|
|
|
|
|
|
|
|
DEVLOCK(orig, pstate); |
|
|
|
|
|
|
|
|
|
snprintf(msgstr, sizeof(msgstr), "USB %s init_intinfo (%d:%d:ii%d)", |
|
|
|
|
orig->drv->dname, |
|
|
|
|
(int)(orig->usbinfo.bus_number), |
|
|
|
|
(int)(orig->usbinfo.device_address), |
|
|
|
|
orig->usbdev->found->which_intinfo); |
|
|
|
|
|
|
|
|
|
if (orig->usbinfo.nodev) { |
|
|
|
|
applog(LOG_ERR, "%s cgpu has nodev", msgstr); |
|
|
|
|
goto Hitagi; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (orig->usbdev->found->which_intinfo != 0) { |
|
|
|
|
applog(LOG_ERR, "%s incorrect cgpu (must be ii0)", msgstr); |
|
|
|
|
goto Hitagi; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (orig->usbdev->found->intinfo_count < 2) { |
|
|
|
|
applog(LOG_ERR, "%s cgpu only has 1 interface", msgstr); |
|
|
|
|
goto Hitagi; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (intinfo < 1 || intinfo >= orig->usbdev->found->intinfo_count) { |
|
|
|
|
applog(LOG_ERR, "%s invalid intinfo (%d) must be > 0 && < %d", |
|
|
|
|
msgstr, intinfo, orig->usbdev->found->intinfo_count); |
|
|
|
|
goto Hitagi; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dev = libusb_get_device(orig->usbdev->handle); |
|
|
|
|
|
|
|
|
|
copy = usb_dup_cgpu(orig, intinfo); |
|
|
|
|
if (!copy) |
|
|
|
|
goto Hitagi; |
|
|
|
|
|
|
|
|
|
found = copy->usbdev->found; |
|
|
|
|
|
|
|
|
|
snprintf(devpath, sizeof(devpath), "%d:%d:%d", |
|
|
|
|
(int)(copy->usbinfo.bus_number), |
|
|
|
|
(int)(copy->usbinfo.device_address), |
|
|
|
|
intinfo); |
|
|
|
|
|
|
|
|
|
copy->device_path = strdup(devpath); |
|
|
|
|
|
|
|
|
|
snprintf(devstr, sizeof(devstr), "- %s device %s", found->name, devpath); |
|
|
|
|
|
|
|
|
|
cg_wlock(&cgusb_fd_lock); |
|
|
|
|
err = libusb_open(dev, &(copy->usbdev->handle)); |
|
|
|
|
cg_wunlock(&cgusb_fd_lock); |
|
|
|
|
if (err) { |
|
|
|
|
switch (err) { |
|
|
|
|
case LIBUSB_ERROR_ACCESS: |
|
|
|
|
applog(LOG_ERR, |
|
|
|
|
"USB init_intinfo, open device failed, err %d, " |
|
|
|
|
"you don't have privilege to access %s", |
|
|
|
|
err, devstr); |
|
|
|
|
break; |
|
|
|
|
#ifdef WIN32 |
|
|
|
|
// Windows specific message
|
|
|
|
|
case LIBUSB_ERROR_NOT_SUPPORTED: |
|
|
|
|
applog(LOG_ERR, |
|
|
|
|
"USB init_intinfo, open device failed, err %d, " |
|
|
|
|
"you need to install a WinUSB driver for %s", |
|
|
|
|
err, devstr); |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
default: |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init_intinfo, open failed, err %d %s", |
|
|
|
|
err, devstr); |
|
|
|
|
} |
|
|
|
|
goto Hitagi; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef WIN32 |
|
|
|
|
if (libusb_kernel_driver_active(copy->usbdev->handle, FOUNDIF(found)) == 1) { |
|
|
|
|
applog(LOG_DEBUG, "USB init_intinfo, kernel attached ... %s", devstr); |
|
|
|
|
err = libusb_detach_kernel_driver(copy->usbdev->handle, FOUNDIF(found)); |
|
|
|
|
if (err == 0) { |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init_intinfo, kernel detached interface %d successfully %s", |
|
|
|
|
FOUNDIF(found), devstr); |
|
|
|
|
} else { |
|
|
|
|
applog(LOG_WARNING, |
|
|
|
|
"USB init_intinfo, kernel detach interface %d failed, err %d in use? %s", |
|
|
|
|
FOUNDIF(found), err, devstr); |
|
|
|
|
goto HitagiClose; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
err = libusb_claim_interface(copy->usbdev->handle, FOUNDIF(found)); |
|
|
|
|
if (err) { |
|
|
|
|
switch(err) { |
|
|
|
|
case LIBUSB_ERROR_BUSY: |
|
|
|
|
applog(LOG_WARNING, |
|
|
|
|
"USB init_intinfo, claim interface %d in use %s", |
|
|
|
|
FOUNDIF(found), devstr); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
applog(LOG_DEBUG, |
|
|
|
|
"USB init_intinfo, claim interface %d failed, err %d %s", |
|
|
|
|
FOUNDIF(found), err, devstr); |
|
|
|
|
} |
|
|
|
|
goto HitagiClose; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
goto Hitagi; |
|
|
|
|
|
|
|
|
|
HitagiClose: |
|
|
|
|
|
|
|
|
|
cg_wlock(&cgusb_fd_lock); |
|
|
|
|
libusb_close(copy->usbdev->handle); |
|
|
|
|
copy->usbdev->handle = NULL; |
|
|
|
|
cg_wunlock(&cgusb_fd_lock); |
|
|
|
|
|
|
|
|
|
copy->usbdev = free_cgusb(copy->usbdev); |
|
|
|
|
|
|
|
|
|
copy = usb_free_cgpu(copy); |
|
|
|
|
|
|
|
|
|
Hitagi: |
|
|
|
|
|
|
|
|
|
DEVUNLOCK(orig, pstate); |
|
|
|
|
|
|
|
|
|
return copy; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found_match) |
|
|
|
|
{ |
|
|
|
|
struct usb_find_devices *found_use = NULL; |
|
|
|
|