Browse Source

ubsutils interfaces much each have their own handle

nfactor-troky
Kano 11 years ago
parent
commit
166147a803
  1. 255
      usbutils.c
  2. 2
      usbutils.h

255
usbutils.c

@ -1379,6 +1379,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
if (cgusb->prod_string && cgusb->prod_string != BLANK) if (cgusb->prod_string && cgusb->prod_string != BLANK)
free(cgusb->prod_string); free(cgusb->prod_string);
if (cgusb->descriptor)
free(cgusb->descriptor); free(cgusb->descriptor);
free(cgusb->found); free(cgusb->found);
@ -1391,7 +1392,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
return NULL; return NULL;
} }
void _usb_uninit(struct cgpu_info *cgpu) static void _usb_uninit(struct cgpu_info *cgpu)
{ {
applog(LOG_DEBUG, "USB uninit %s%i", applog(LOG_DEBUG, "USB uninit %s%i",
cgpu->drv->name, cgpu->device_id); cgpu->drv->name, cgpu->device_id);
@ -1400,18 +1401,12 @@ void _usb_uninit(struct cgpu_info *cgpu)
// if release_cgpu() was called due to a USB NODEV(err) // if release_cgpu() was called due to a USB NODEV(err)
if (!cgpu->usbdev) if (!cgpu->usbdev)
return; return;
if (cgpu->usbdev->handle) { if (cgpu->usbdev->handle) {
int ifinfo = 0; libusb_release_interface(cgpu->usbdev->handle, USBIF(cgpu->usbdev));
while (cgpu->usbdev->claimed > 0) {
libusb_release_interface(cgpu->usbdev->handle,
cgpu->usbdev->found->intinfos[ifinfo].interface);
ifinfo++;
cgpu->usbdev->claimed--;
}
cg_wlock(&cgusb_fd_lock); cg_wlock(&cgusb_fd_lock);
libusb_close(cgpu->usbdev->handle); libusb_close(cgpu->usbdev->handle);
cgpu->usbdev->handle = NULL; cgpu->usbdev->handle = NULL;
cgpu->usbdev->claimed = 0;
cg_wunlock(&cgusb_fd_lock); cg_wunlock(&cgusb_fd_lock);
} }
cgpu->usbdev = free_cgusb(cgpu->usbdev); cgpu->usbdev = free_cgusb(cgpu->usbdev);
@ -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); 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 *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)) if (unlikely(!copy))
quit(1, "Failed to calloc cgpu for %s in usb_copy_cgpu", orig->drv->dname); 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)
copy->usbinfo.devlock = orig->usbinfo.devlock; 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; return copy;
} }
@ -1616,24 +1680,20 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
} }
#ifndef WIN32 #ifndef WIN32
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) { if (libusb_kernel_driver_active(cgusb->handle, FOUNDIF(found)) == 1) {
int interface = found->intinfos[ifinfo].interface;
if (libusb_kernel_driver_active(cgusb->handle, interface) == 1) {
applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr);
err = libusb_detach_kernel_driver(cgusb->handle, interface); err = libusb_detach_kernel_driver(cgusb->handle, FOUNDIF(found));
if (err == 0) { if (err == 0) {
applog(LOG_DEBUG, applog(LOG_DEBUG,
"USB init, kernel detached interface %d successfully %s", "USB init, kernel detached interface %d successfully %s",
interface, devstr); FOUNDIF(found), devstr);
} else { } else {
applog(LOG_WARNING, applog(LOG_WARNING,
"USB init, kernel detach interface %d failed, err %d in use? %s", "USB init, kernel detach interface %d failed, err %d in use? %s",
interface, err, devstr); FOUNDIF(found), err, devstr);
goto cldame; goto cldame;
} }
} }
}
#endif #endif
if (found->iManufacturer) { if (found->iManufacturer) {
@ -1754,26 +1814,21 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
goto cldame; goto cldame;
} }
cgusb->claimed = 0; err = libusb_claim_interface(cgusb->handle, FOUNDIF(found));
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) {
int interface = found->intinfos[ifinfo].interface;
err = libusb_claim_interface(cgusb->handle, interface);
if (err) { if (err) {
switch(err) { switch(err) {
case LIBUSB_ERROR_BUSY: case LIBUSB_ERROR_BUSY:
applog(LOG_WARNING, applog(LOG_WARNING,
"USB init, claim interface %d in use %s", "USB init, claim interface %d in use %s",
interface, devstr); FOUNDIF(found), devstr);
break; break;
default: default:
applog(LOG_DEBUG, applog(LOG_DEBUG,
"USB init, claim interface %d failed, err %d %s", "USB init, claim interface %d failed, err %d %s",
interface, err, devstr); FOUNDIF(found), err, devstr);
} }
goto reldame; goto reldame;
} }
cgusb->claimed++;
}
cfg = -1; cfg = -1;
err = libusb_get_configuration(cgusb->handle, &cfg); err = libusb_get_configuration(cgusb->handle, &cfg);
@ -1839,19 +1894,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
reldame: reldame:
ifinfo = 0; libusb_release_interface(cgusb->handle, FOUNDIF(found));
while (cgusb->claimed > 0) {
libusb_release_interface(cgusb->handle, found->intinfos[ifinfo].interface);
ifinfo++;
cgusb->claimed--;
}
cldame: cldame:
cg_wlock(&cgusb_fd_lock); cg_wlock(&cgusb_fd_lock);
libusb_close(cgusb->handle); libusb_close(cgusb->handle);
cgusb->handle = NULL; cgusb->handle = NULL;
cgusb->claimed = 0;
cg_wunlock(&cgusb_fd_lock); cg_wunlock(&cgusb_fd_lock);
dame: dame:
@ -1867,6 +1916,144 @@ out_unlock:
return bad; 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) bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found_match)
{ {
struct usb_find_devices *found_use = NULL; struct usb_find_devices *found_use = NULL;

2
usbutils.h

@ -177,7 +177,6 @@ enum usb_types {
struct cg_usb_device { struct cg_usb_device {
struct usb_find_devices *found; struct usb_find_devices *found;
libusb_device_handle *handle; libusb_device_handle *handle;
int claimed;
pthread_mutex_t *mutex; pthread_mutex_t *mutex;
struct libusb_device_descriptor *descriptor; struct libusb_device_descriptor *descriptor;
enum usb_types usb_type; enum usb_types usb_type;
@ -336,6 +335,7 @@ struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads);
struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devlock); struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devlock);
#define usb_free_cgpu(cgpu) usb_free_cgpu_devlock(cgpu, true) #define usb_free_cgpu(cgpu) usb_free_cgpu_devlock(cgpu, true)
void usb_uninit(struct cgpu_info *cgpu); void usb_uninit(struct cgpu_info *cgpu);
struct cgpu_info *usb_init_intinfo(struct cgpu_info *orig, int intinfo);
bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found);
void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *));
struct api_data *api_usb_stats(int *count); struct api_data *api_usb_stats(int *count);

Loading…
Cancel
Save