|
|
@ -94,10 +94,18 @@ |
|
|
|
|
|
|
|
|
|
|
|
#define USB_EPS(_intx, _epinfosx) { \ |
|
|
|
#define USB_EPS(_intx, _epinfosx) { \ |
|
|
|
.interface = _intx, \ |
|
|
|
.interface = _intx, \ |
|
|
|
|
|
|
|
.ctrl_transfer = _intx, \ |
|
|
|
.epinfo_count = ARRAY_SIZE(_epinfosx), \ |
|
|
|
.epinfo_count = ARRAY_SIZE(_epinfosx), \ |
|
|
|
.epinfos = _epinfosx \ |
|
|
|
.epinfos = _epinfosx \ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define USB_EPS_CTRL(_inty, _ctrlinty, _epinfosy) { \ |
|
|
|
|
|
|
|
.interface = _inty, \ |
|
|
|
|
|
|
|
.ctrl_transfer = _ctrlinty, \ |
|
|
|
|
|
|
|
.epinfo_count = ARRAY_SIZE(_epinfosy), \ |
|
|
|
|
|
|
|
.epinfos = _epinfosy \ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BFLSC |
|
|
|
#ifdef USE_BFLSC |
|
|
|
// N.B. transfer size is 512 with USB2.0, but only 64 with USB1.1
|
|
|
|
// N.B. transfer size is 512 with USB2.0, but only 64 with USB1.1
|
|
|
|
static struct usb_epinfo bas_epinfos[] = { |
|
|
|
static struct usb_epinfo bas_epinfos[] = { |
|
|
@ -196,7 +204,6 @@ static struct usb_epinfo cmr2_epinfos0[] = { |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } |
|
|
|
}; |
|
|
|
}; |
|
|
|
#ifndef WIN32 |
|
|
|
|
|
|
|
static struct usb_epinfo cmr2_epinfos1[] = { |
|
|
|
static struct usb_epinfo cmr2_epinfos1[] = { |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(4), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(4), 0 }, |
|
|
@ -209,29 +216,24 @@ static struct usb_epinfo cmr2_epinfos3[] = { |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(7), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(7), 0 }, |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(8), 0 } |
|
|
|
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(8), 0 } |
|
|
|
}; |
|
|
|
}; |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct usb_intinfo cmr2_ints[] = { |
|
|
|
static struct usb_intinfo cmr2_ints[] = { |
|
|
|
USB_EPS(0, cmr2_epinfos0) |
|
|
|
USB_EPS_CTRL(0, 1, cmr2_epinfos0), |
|
|
|
#ifndef WIN32 |
|
|
|
USB_EPS_CTRL(1, 2, cmr2_epinfos1), |
|
|
|
, |
|
|
|
USB_EPS_CTRL(2, 3, cmr2_epinfos2), |
|
|
|
USB_EPS(1, cmr2_epinfos1), |
|
|
|
USB_EPS_CTRL(3, 4, cmr2_epinfos3) |
|
|
|
USB_EPS(2, cmr2_epinfos2), |
|
|
|
|
|
|
|
USB_EPS(3, cmr2_epinfos3) |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#define IDVENDOR_FTDI 0x0403 |
|
|
|
#define IDVENDOR_FTDI 0x0403 |
|
|
|
|
|
|
|
|
|
|
|
#define INTINFO(_ints) \ |
|
|
|
#define INTINFO(_ints) \ |
|
|
|
.which_intinfo = 0, \ |
|
|
|
|
|
|
|
.intinfo_count = ARRAY_SIZE(_ints), \ |
|
|
|
.intinfo_count = ARRAY_SIZE(_ints), \ |
|
|
|
.intinfos = _ints |
|
|
|
.intinfos = _ints |
|
|
|
|
|
|
|
|
|
|
|
#define USBEP(_usbdev, _epinfo) (_usbdev->found->intinfos[_usbdev->found->which_intinfo].epinfos[_epinfo].ep) |
|
|
|
#define USBEP(_usbdev, _intinfo, _epinfo) (_usbdev->found->intinfos[_intinfo].epinfos[_epinfo].ep) |
|
|
|
#define FOUNDIF(_found) (_found->intinfos[_found->which_intinfo].interface) |
|
|
|
#define THISIF(_found, _this) (_found->intinfos[_this].interface) |
|
|
|
#define USBIF(_usbdev) FOUNDIF(_usbdev->found) |
|
|
|
#define USBIF(_usbdev, _this) THISIF(_usbdev->found, _this) |
|
|
|
|
|
|
|
|
|
|
|
// TODO: Add support for (at least) Isochronous endpoints
|
|
|
|
// TODO: Add support for (at least) Isochronous endpoints
|
|
|
|
static struct usb_find_devices find_dev[] = { |
|
|
|
static struct usb_find_devices find_dev[] = { |
|
|
@ -392,11 +394,10 @@ static struct usb_find_devices find_dev[] = { |
|
|
|
.config = 1, |
|
|
|
.config = 1, |
|
|
|
.timeout = 100, |
|
|
|
.timeout = 100, |
|
|
|
.latency = LATENCY_UNUSED, |
|
|
|
.latency = LATENCY_UNUSED, |
|
|
|
.which_intinfo = 0, |
|
|
|
|
|
|
|
.intinfo_count = 0, |
|
|
|
.intinfo_count = 0, |
|
|
|
.intinfos = NULL }, |
|
|
|
.intinfos = NULL }, |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
{ DRV_LAST, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL } |
|
|
|
{ DRV_LAST, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, NULL } |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BFLSC |
|
|
|
#ifdef USE_BFLSC |
|
|
@ -1305,6 +1306,8 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) |
|
|
|
|
|
|
|
|
|
|
|
static void _usb_uninit(struct cgpu_info *cgpu) |
|
|
|
static void _usb_uninit(struct cgpu_info *cgpu) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
int ifinfo; |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
@ -1314,7 +1317,10 @@ static void _usb_uninit(struct cgpu_info *cgpu) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu->usbdev->handle) { |
|
|
|
if (cgpu->usbdev->handle) { |
|
|
|
libusb_release_interface(cgpu->usbdev->handle, USBIF(cgpu->usbdev)); |
|
|
|
for (ifinfo = cgpu->usbdev->found->intinfo_count - 1; ifinfo >= 0; ifinfo--) { |
|
|
|
|
|
|
|
libusb_release_interface(cgpu->usbdev->handle, |
|
|
|
|
|
|
|
THISIF(cgpu->usbdev->found, ifinfo)); |
|
|
|
|
|
|
|
} |
|
|
|
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; |
|
|
@ -1342,7 +1348,7 @@ static void release_cgpu(struct cgpu_info *cgpu) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cg_usb_device *cgusb = cgpu->usbdev; |
|
|
|
struct cg_usb_device *cgusb = cgpu->usbdev; |
|
|
|
struct cgpu_info *lookcgpu; |
|
|
|
struct cgpu_info *lookcgpu; |
|
|
|
int which_intinfo, i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "USB release %s%i", |
|
|
|
applog(LOG_DEBUG, "USB release %s%i", |
|
|
|
cgpu->drv->name, cgpu->device_id); |
|
|
|
cgpu->drv->name, cgpu->device_id); |
|
|
@ -1360,7 +1366,6 @@ static void release_cgpu(struct cgpu_info *cgpu) |
|
|
|
cgtime(&cgpu->usbinfo.last_nodev); |
|
|
|
cgtime(&cgpu->usbinfo.last_nodev); |
|
|
|
|
|
|
|
|
|
|
|
// Any devices sharing the same USB device should be marked also
|
|
|
|
// Any devices sharing the same USB device should be marked also
|
|
|
|
// Currently only MMQ shares a USB device
|
|
|
|
|
|
|
|
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) { |
|
|
@ -1375,15 +1380,12 @@ static void release_cgpu(struct cgpu_info *cgpu) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
which_intinfo = cgpu->usbdev->found->which_intinfo; |
|
|
|
|
|
|
|
_usb_uninit(cgpu); |
|
|
|
_usb_uninit(cgpu); |
|
|
|
if (which_intinfo == 0) |
|
|
|
|
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Used by MMQ - use the same usbdev thus locking is across all 4 related devices |
|
|
|
* Use the same usbdev thus locking is across all 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) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1407,80 +1409,11 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig) |
|
|
|
|
|
|
|
|
|
|
|
copy->usbinfo.nodev = (copy->usbdev == NULL); |
|
|
|
copy->usbinfo.nodev = (copy->usbdev == NULL); |
|
|
|
|
|
|
|
|
|
|
|
copy->usbinfo.devlock = orig->usbinfo.devlock; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEVUNLOCK(orig, pstate); |
|
|
|
DEVUNLOCK(orig, pstate); |
|
|
|
|
|
|
|
|
|
|
|
return copy; |
|
|
|
return copy; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Used by CMR - use a different usbdev - since they must use a different |
|
|
|
|
|
|
|
* USB handle due to using different interfaces (libusb requirement) |
|
|
|
|
|
|
|
* N.B. multiple interfaces don't as yet work in windows libusb |
|
|
|
|
|
|
|
* so the CMR defines above that use them are defined out in windows |
|
|
|
|
|
|
|
* Nothing else uses multiple interfaces as at 20130922 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads) |
|
|
|
struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cgpu_info *cgpu = calloc(1, sizeof(*cgpu)); |
|
|
|
struct cgpu_info *cgpu = calloc(1, sizeof(*cgpu)); |
|
|
@ -1533,7 +1466,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u |
|
|
|
char devstr[STRBUFLEN+1]; |
|
|
|
char devstr[STRBUFLEN+1]; |
|
|
|
int err, ifinfo, epinfo, alt, epnum, pstate; |
|
|
|
int err, ifinfo, epinfo, alt, epnum, pstate; |
|
|
|
int bad = USB_INIT_FAIL; |
|
|
|
int bad = USB_INIT_FAIL; |
|
|
|
int cfg; |
|
|
|
int cfg, claimed = 0; |
|
|
|
|
|
|
|
|
|
|
|
DEVLOCK(cgpu, pstate); |
|
|
|
DEVLOCK(cgpu, pstate); |
|
|
|
|
|
|
|
|
|
|
@ -1544,7 +1477,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u |
|
|
|
snprintf(devpath, sizeof(devpath), "%d:%d-i%d", |
|
|
|
snprintf(devpath, sizeof(devpath), "%d:%d-i%d", |
|
|
|
(int)(cgpu->usbinfo.bus_number), |
|
|
|
(int)(cgpu->usbinfo.bus_number), |
|
|
|
(int)(cgpu->usbinfo.device_address), |
|
|
|
(int)(cgpu->usbinfo.device_address), |
|
|
|
FOUNDIF(found)); |
|
|
|
THISIF(found, 0)); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
snprintf(devpath, sizeof(devpath), "%d:%d", |
|
|
|
snprintf(devpath, sizeof(devpath), "%d:%d", |
|
|
|
(int)(cgpu->usbinfo.bus_number), |
|
|
|
(int)(cgpu->usbinfo.bus_number), |
|
|
@ -1606,20 +1539,24 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifndef WIN32 |
|
|
|
#ifndef WIN32 |
|
|
|
if (libusb_kernel_driver_active(cgusb->handle, FOUNDIF(found)) == 1) { |
|
|
|
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) { |
|
|
|
|
|
|
|
if (libusb_kernel_driver_active(cgusb->handle, THISIF(found, ifinfo)) == 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, FOUNDIF(found)); |
|
|
|
err = libusb_detach_kernel_driver(cgusb->handle, THISIF(found, ifinfo)); |
|
|
|
if (err == 0) { |
|
|
|
if (err == 0) { |
|
|
|
applog(LOG_DEBUG, |
|
|
|
applog(LOG_DEBUG, |
|
|
|
"USB init, kernel detached interface %d successfully %s", |
|
|
|
"USB init, kernel detached ifinfo %d interface %d" |
|
|
|
FOUNDIF(found), devstr); |
|
|
|
" successfully %s", |
|
|
|
|
|
|
|
ifinfo, THISIF(found, ifinfo), 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 ifinfo %d interface %d failed," |
|
|
|
FOUNDIF(found), err, devstr); |
|
|
|
" err %d in use? %s", |
|
|
|
|
|
|
|
ifinfo, THISIF(found, ifinfo), err, devstr); |
|
|
|
goto cldame; |
|
|
|
goto cldame; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if (found->iManufacturer) { |
|
|
|
if (found->iManufacturer) { |
|
|
@ -1740,21 +1677,27 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u |
|
|
|
goto cldame; |
|
|
|
goto cldame; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = libusb_claim_interface(cgusb->handle, FOUNDIF(found)); |
|
|
|
claimed = 0; |
|
|
|
if (err) { |
|
|
|
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) { |
|
|
|
|
|
|
|
err = libusb_claim_interface(cgusb->handle, THISIF(found, ifinfo)); |
|
|
|
|
|
|
|
if (err == 0) |
|
|
|
|
|
|
|
claimed++; |
|
|
|
|
|
|
|
else { |
|
|
|
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 ifinfo %d interface %d in use %s", |
|
|
|
FOUNDIF(found), devstr); |
|
|
|
ifinfo, THISIF(found, ifinfo), devstr); |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
applog(LOG_DEBUG, |
|
|
|
applog(LOG_DEBUG, |
|
|
|
"USB init, claim interface %d failed, err %d %s", |
|
|
|
"USB init, claim ifinfo %d interface %d failed," |
|
|
|
FOUNDIF(found), err, devstr); |
|
|
|
" err %d %s", |
|
|
|
|
|
|
|
ifinfo, THISIF(found, ifinfo), err, devstr); |
|
|
|
} |
|
|
|
} |
|
|
|
goto reldame; |
|
|
|
goto reldame; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cfg = -1; |
|
|
|
cfg = -1; |
|
|
|
err = libusb_get_configuration(cgusb->handle, &cfg); |
|
|
|
err = libusb_get_configuration(cgusb->handle, &cfg); |
|
|
@ -1820,7 +1763,9 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u |
|
|
|
|
|
|
|
|
|
|
|
reldame: |
|
|
|
reldame: |
|
|
|
|
|
|
|
|
|
|
|
libusb_release_interface(cgusb->handle, FOUNDIF(found)); |
|
|
|
ifinfo = claimed; |
|
|
|
|
|
|
|
while (ifinfo-- > 0) |
|
|
|
|
|
|
|
libusb_release_interface(cgusb->handle, THISIF(found, ifinfo)); |
|
|
|
|
|
|
|
|
|
|
|
cldame: |
|
|
|
cldame: |
|
|
|
|
|
|
|
|
|
|
@ -1842,144 +1787,6 @@ 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-i%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 i0)", 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-i%d", |
|
|
|
|
|
|
|
(int)(copy->usbinfo.bus_number), |
|
|
|
|
|
|
|
(int)(copy->usbinfo.device_address), |
|
|
|
|
|
|
|
FOUNDIF(found)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
@ -2543,7 +2350,7 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, |
|
|
|
return err; |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int _usb_read(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, enum usb_cmds cmd, bool readonce) |
|
|
|
int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, enum usb_cmds cmd, bool readonce) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cg_usb_device *usbdev; |
|
|
|
struct cg_usb_device *usbdev; |
|
|
|
bool ftdi; |
|
|
|
bool ftdi; |
|
|
@ -2571,7 +2378,7 @@ int _usb_read(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int |
|
|
|
usbdev = cgpu->usbdev; |
|
|
|
usbdev = cgpu->usbdev; |
|
|
|
ftdi = (usbdev->usb_type == USB_TYPE_FTDI); |
|
|
|
ftdi = (usbdev->usb_type == USB_TYPE_FTDI); |
|
|
|
|
|
|
|
|
|
|
|
USBDEBUG("USB debug: _usb_read(%s (nodev=%s),epinfo=%d,buf=%p,bufsiz=%zu,proc=%p,timeout=%u,end=%s,cmd=%s,ftdi=%s,readonce=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), epinfo, buf, bufsiz, processed, timeout, end ? (char *)str_text((char *)end) : "NULL", usb_cmdname(cmd), bool_str(ftdi), bool_str(readonce)); |
|
|
|
USBDEBUG("USB debug: _usb_read(%s (nodev=%s),intinfo=%d,epinfo=%d,buf=%p,bufsiz=%zu,proc=%p,timeout=%u,end=%s,cmd=%s,ftdi=%s,readonce=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), intinfo, epinfo, buf, bufsiz, processed, timeout, end ? (char *)str_text((char *)end) : "NULL", usb_cmdname(cmd), bool_str(ftdi), bool_str(readonce)); |
|
|
|
|
|
|
|
|
|
|
|
if (bufsiz > USB_MAX_READ) |
|
|
|
if (bufsiz > USB_MAX_READ) |
|
|
|
quit(1, "%s USB read request %d too large (max=%d)", cgpu->drv->name, (int)bufsiz, USB_MAX_READ); |
|
|
|
quit(1, "%s USB read request %d too large (max=%d)", cgpu->drv->name, (int)bufsiz, USB_MAX_READ); |
|
|
@ -2625,7 +2432,7 @@ int _usb_read(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
err = usb_bulk_transfer(usbdev->handle, |
|
|
|
err = usb_bulk_transfer(usbdev->handle, |
|
|
|
USBEP(usbdev, epinfo), |
|
|
|
USBEP(usbdev, intinfo, epinfo), |
|
|
|
ptr, usbbufread, &got, timeout, |
|
|
|
ptr, usbbufread, &got, timeout, |
|
|
|
cgpu, MODE_BULK_READ, cmd, first ? SEQ0 : SEQ1); |
|
|
|
cgpu, MODE_BULK_READ, cmd, first ? SEQ0 : SEQ1); |
|
|
|
cgtime(&tv_finish); |
|
|
|
cgtime(&tv_finish); |
|
|
@ -2729,7 +2536,7 @@ int _usb_read(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
err = usb_bulk_transfer(usbdev->handle, |
|
|
|
err = usb_bulk_transfer(usbdev->handle, |
|
|
|
USBEP(usbdev, epinfo), ptr, |
|
|
|
USBEP(usbdev, intinfo, epinfo), ptr, |
|
|
|
usbbufread, &got, timeout, |
|
|
|
usbbufread, &got, timeout, |
|
|
|
cgpu, MODE_BULK_READ, cmd, first ? SEQ0 : SEQ1); |
|
|
|
cgpu, MODE_BULK_READ, cmd, first ? SEQ0 : SEQ1); |
|
|
|
cgtime(&tv_finish); |
|
|
|
cgtime(&tv_finish); |
|
|
@ -2816,7 +2623,7 @@ out_unlock: |
|
|
|
return err; |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int _usb_write(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds cmd) |
|
|
|
int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds cmd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cg_usb_device *usbdev; |
|
|
|
struct cg_usb_device *usbdev; |
|
|
|
struct timeval read_start, tv_finish; |
|
|
|
struct timeval read_start, tv_finish; |
|
|
@ -2827,7 +2634,7 @@ int _usb_write(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int |
|
|
|
|
|
|
|
|
|
|
|
DEVLOCK(cgpu, pstate); |
|
|
|
DEVLOCK(cgpu, pstate); |
|
|
|
|
|
|
|
|
|
|
|
USBDEBUG("USB debug: _usb_write(%s (nodev=%s),epinfo=%d,buf='%s',bufsiz=%zu,proc=%p,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), epinfo, (char *)str_text(buf), bufsiz, processed, timeout, usb_cmdname(cmd)); |
|
|
|
USBDEBUG("USB debug: _usb_write(%s (nodev=%s),intinfo=%d,epinfo=%d,buf='%s',bufsiz=%zu,proc=%p,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), intinfo, epinfo, (char *)str_text(buf), bufsiz, processed, timeout, usb_cmdname(cmd)); |
|
|
|
|
|
|
|
|
|
|
|
*processed = 0; |
|
|
|
*processed = 0; |
|
|
|
|
|
|
|
|
|
|
@ -2870,7 +2677,7 @@ int _usb_write(struct cgpu_info *cgpu, int epinfo, char *buf, size_t bufsiz, int |
|
|
|
usbdev->last_write_siz = bufsiz; |
|
|
|
usbdev->last_write_siz = bufsiz; |
|
|
|
} |
|
|
|
} |
|
|
|
err = usb_bulk_transfer(usbdev->handle, |
|
|
|
err = usb_bulk_transfer(usbdev->handle, |
|
|
|
USBEP(usbdev, epinfo), |
|
|
|
USBEP(usbdev, intinfo, epinfo), |
|
|
|
(unsigned char *)buf, bufsiz, &sent, |
|
|
|
(unsigned char *)buf, bufsiz, &sent, |
|
|
|
timeout, cgpu, MODE_BULK_WRITE, cmd, first ? SEQ0 : SEQ1); |
|
|
|
timeout, cgpu, MODE_BULK_WRITE, cmd, first ? SEQ0 : SEQ1); |
|
|
|
cgtime(&tv_finish); |
|
|
|
cgtime(&tv_finish); |
|
|
@ -3087,7 +2894,7 @@ int usb_ftdi_cts(struct cgpu_info *cgpu) |
|
|
|
return (ret & FTDI_RS0_CTS); |
|
|
|
return (ret & FTDI_RS0_CTS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int usb_ftdi_set_latency(struct cgpu_info *cgpu) |
|
|
|
int _usb_ftdi_set_latency(struct cgpu_info *cgpu, int intinfo) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int err = 0; |
|
|
|
int err = 0; |
|
|
|
int pstate; |
|
|
|
int pstate; |
|
|
@ -3108,7 +2915,7 @@ int usb_ftdi_set_latency(struct cgpu_info *cgpu) |
|
|
|
if (!err) |
|
|
|
if (!err) |
|
|
|
err = __usb_transfer(cgpu, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY, |
|
|
|
err = __usb_transfer(cgpu, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY, |
|
|
|
cgpu->usbdev->found->latency, |
|
|
|
cgpu->usbdev->found->latency, |
|
|
|
USBIF(cgpu->usbdev), |
|
|
|
USBIF(cgpu->usbdev, intinfo), |
|
|
|
NULL, 0, DEVTIMEOUT, C_LATENCY); |
|
|
|
NULL, 0, DEVTIMEOUT, C_LATENCY); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3226,8 +3033,10 @@ void usb_disable_cps(struct cgpu_info *cgpu) |
|
|
|
* The value returned (0) when usbdev is NULL |
|
|
|
* The value returned (0) when usbdev is NULL |
|
|
|
* doesn't matter since it also means the next call to |
|
|
|
* doesn't matter since it also means the next call to |
|
|
|
* any usbutils function will fail with a nodev |
|
|
|
* any usbutils function will fail with a nodev |
|
|
|
|
|
|
|
* N.B. this is to get the interface number to use in a control_transfer |
|
|
|
|
|
|
|
* which for some devices isn't actually the interface number |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
int usb_interface(struct cgpu_info *cgpu) |
|
|
|
int _usb_interface(struct cgpu_info *cgpu, int intinfo) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int interface = 0; |
|
|
|
int interface = 0; |
|
|
|
int pstate; |
|
|
|
int pstate; |
|
|
@ -3235,7 +3044,7 @@ int usb_interface(struct cgpu_info *cgpu) |
|
|
|
DEVLOCK(cgpu, pstate); |
|
|
|
DEVLOCK(cgpu, pstate); |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu->usbdev) |
|
|
|
if (cgpu->usbdev) |
|
|
|
interface = USBIF(cgpu->usbdev); |
|
|
|
interface = cgpu->usbdev->found->intinfos[intinfo].ctrl_transfer; |
|
|
|
|
|
|
|
|
|
|
|
DEVUNLOCK(cgpu, pstate); |
|
|
|
DEVUNLOCK(cgpu, pstate); |
|
|
|
|
|
|
|
|
|
|
|