Browse Source

Merge pull request #492 from kanoi/master

usbutils handle multiple interfaces
nfactor-troky
kanoi 11 years ago
parent
commit
9ccb3a8f11
  1. 2
      driver-avalon.c
  2. 17
      driver-bflsc.c
  3. 17
      driver-bitforce.c
  4. 76
      driver-icarus.c
  5. 564
      usbutils.c
  6. 20
      usbutils.h

2
driver-avalon.c

@ -531,7 +531,7 @@ static void avalon_initialise(struct cgpu_info *avalon)
if (avalon->usbinfo.nodev) if (avalon->usbinfo.nodev)
return; return;
interface = avalon->usbdev->found->interface; interface = usb_interface(avalon);
// Reset // Reset
err = usb_transfer(avalon, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(avalon, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_RESET, interface, C_RESET); FTDI_VALUE_RESET, interface, C_RESET);

17
driver-bflsc.c

@ -452,7 +452,7 @@ static bool bflsc_qres(struct cgpu_info *bflsc, char *buf, size_t bufsiz, int de
static void __bflsc_initialise(struct cgpu_info *bflsc) static void __bflsc_initialise(struct cgpu_info *bflsc)
{ {
int err; int err, interface;
// TODO: does x-link bypass the other device FTDI? (I think it does) // TODO: does x-link bypass the other device FTDI? (I think it does)
// So no initialisation required except for the master device? // So no initialisation required except for the master device?
@ -460,9 +460,10 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
if (bflsc->usbinfo.nodev) if (bflsc->usbinfo.nodev)
return; return;
interface = usb_interface(bflsc);
// Reset // Reset
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_RESET, bflsc->usbdev->found->interface, C_RESET); FTDI_VALUE_RESET, interface, C_RESET);
applog(LOG_DEBUG, "%s%i: reset got err %d", applog(LOG_DEBUG, "%s%i: reset got err %d",
bflsc->drv->name, bflsc->device_id, err); bflsc->drv->name, bflsc->device_id, err);
@ -477,7 +478,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
// Set data control // Set data control
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_DATA,
FTDI_VALUE_DATA_BAS, bflsc->usbdev->found->interface, C_SETDATA); FTDI_VALUE_DATA_BAS, interface, C_SETDATA);
applog(LOG_DEBUG, "%s%i: setdata got err %d", applog(LOG_DEBUG, "%s%i: setdata got err %d",
bflsc->drv->name, bflsc->device_id, err); bflsc->drv->name, bflsc->device_id, err);
@ -487,7 +488,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
// Set the baud // Set the baud
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BAS, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BAS,
(FTDI_INDEX_BAUD_BAS & 0xff00) | bflsc->usbdev->found->interface, (FTDI_INDEX_BAUD_BAS & 0xff00) | interface,
C_SETBAUD); C_SETBAUD);
applog(LOG_DEBUG, "%s%i: setbaud got err %d", applog(LOG_DEBUG, "%s%i: setbaud got err %d",
@ -498,7 +499,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
// Set Flow Control // Set Flow Control
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW,
FTDI_VALUE_FLOW, bflsc->usbdev->found->interface, C_SETFLOW); FTDI_VALUE_FLOW, interface, C_SETFLOW);
applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", applog(LOG_DEBUG, "%s%i: setflowctrl got err %d",
bflsc->drv->name, bflsc->device_id, err); bflsc->drv->name, bflsc->device_id, err);
@ -508,7 +509,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
// Set Modem Control // Set Modem Control
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM,
FTDI_VALUE_MODEM, bflsc->usbdev->found->interface, C_SETMODEM); FTDI_VALUE_MODEM, interface, C_SETMODEM);
applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d",
bflsc->drv->name, bflsc->device_id, err); bflsc->drv->name, bflsc->device_id, err);
@ -518,7 +519,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
// Clear any sent data // Clear any sent data
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_PURGE_TX, bflsc->usbdev->found->interface, C_PURGETX); FTDI_VALUE_PURGE_TX, interface, C_PURGETX);
applog(LOG_DEBUG, "%s%i: purgetx got err %d", applog(LOG_DEBUG, "%s%i: purgetx got err %d",
bflsc->drv->name, bflsc->device_id, err); bflsc->drv->name, bflsc->device_id, err);
@ -528,7 +529,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
// Clear any received data // Clear any received data
err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_PURGE_RX, bflsc->usbdev->found->interface, C_PURGERX); FTDI_VALUE_PURGE_RX, interface, C_PURGERX);
applog(LOG_DEBUG, "%s%i: purgerx got err %d", applog(LOG_DEBUG, "%s%i: purgerx got err %d",
bflsc->drv->name, bflsc->device_id, err); bflsc->drv->name, bflsc->device_id, err);

17
driver-bitforce.c

@ -81,7 +81,7 @@ struct device_drv bitforce_drv;
static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
{ {
int err; int err, interface;
if (lock) if (lock)
mutex_lock(&bitforce->device_mutex); mutex_lock(&bitforce->device_mutex);
@ -89,9 +89,10 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
if (bitforce->usbinfo.nodev) if (bitforce->usbinfo.nodev)
goto failed; goto failed;
interface = usb_interface(bitforce);
// Reset // Reset
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET); FTDI_VALUE_RESET, interface, C_RESET);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: reset got err %d", applog(LOG_DEBUG, "%s%i: reset got err %d",
bitforce->drv->name, bitforce->device_id, err); bitforce->drv->name, bitforce->device_id, err);
@ -101,7 +102,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
// Set data control // Set data control
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA,
FTDI_VALUE_DATA_BFL, bitforce->usbdev->found->interface, C_SETDATA); FTDI_VALUE_DATA_BFL, interface, C_SETDATA);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: setdata got err %d", applog(LOG_DEBUG, "%s%i: setdata got err %d",
bitforce->drv->name, bitforce->device_id, err); bitforce->drv->name, bitforce->device_id, err);
@ -111,7 +112,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
// Set the baud // Set the baud
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BFL, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BFL,
(FTDI_INDEX_BAUD_BFL & 0xff00) | bitforce->usbdev->found->interface, (FTDI_INDEX_BAUD_BFL & 0xff00) | interface,
C_SETBAUD); C_SETBAUD);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: setbaud got err %d", applog(LOG_DEBUG, "%s%i: setbaud got err %d",
@ -122,7 +123,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
// Set Flow Control // Set Flow Control
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW,
FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); FTDI_VALUE_FLOW, interface, C_SETFLOW);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", applog(LOG_DEBUG, "%s%i: setflowctrl got err %d",
bitforce->drv->name, bitforce->device_id, err); bitforce->drv->name, bitforce->device_id, err);
@ -132,7 +133,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
// Set Modem Control // Set Modem Control
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM,
FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); FTDI_VALUE_MODEM, interface, C_SETMODEM);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d",
bitforce->drv->name, bitforce->device_id, err); bitforce->drv->name, bitforce->device_id, err);
@ -142,7 +143,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
// Clear any sent data // Clear any sent data
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); FTDI_VALUE_PURGE_TX, interface, C_PURGETX);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: purgetx got err %d", applog(LOG_DEBUG, "%s%i: purgetx got err %d",
bitforce->drv->name, bitforce->device_id, err); bitforce->drv->name, bitforce->device_id, err);
@ -152,7 +153,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
// Clear any received data // Clear any received data
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); FTDI_VALUE_PURGE_RX, interface, C_PURGERX);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "%s%i: purgerx got err %d", applog(LOG_DEBUG, "%s%i: purgerx got err %d",
bitforce->drv->name, bitforce->device_id, err); bitforce->drv->name, bitforce->device_id, err);

76
driver-icarus.c

@ -102,7 +102,9 @@ ASSERT1(sizeof(uint32_t) == 4);
#define LANCELOT_HASH_TIME 0.0000000025000 #define LANCELOT_HASH_TIME 0.0000000025000
#define ASICMINERUSB_HASH_TIME 0.0000000029761 #define ASICMINERUSB_HASH_TIME 0.0000000029761
// TODO: What is it? // TODO: What is it?
#define CAIRNSMORE1_HASH_TIME 0.0000000026316 #define CAIRNSMORE1_HASH_TIME 0.0000000027000
// Per FPGA
#define CAIRNSMORE2_HASH_TIME 0.0000000066600
#define NANOSEC 1000000000.0 #define NANOSEC 1000000000.0
// Icarus Rev3 doesn't send a completion message when it finishes // Icarus Rev3 doesn't send a completion message when it finishes
@ -208,6 +210,8 @@ struct ICARUS_INFO {
int work_division; int work_division;
int fpga_count; int fpga_count;
uint32_t nonce_mask; uint32_t nonce_mask;
bool initialised;
}; };
#define END_CONDITION 0x0000ffff #define END_CONDITION 0x0000ffff
@ -262,6 +266,7 @@ static void _transfer(struct cgpu_info *icarus, uint8_t request_type, uint8_t bR
static void icarus_initialise(struct cgpu_info *icarus, int baud) static void icarus_initialise(struct cgpu_info *icarus, int baud)
{ {
struct ICARUS_INFO *info = (struct ICARUS_INFO *)(icarus->device_data);
uint16_t wValue, wIndex; uint16_t wValue, wIndex;
enum sub_ident ident; enum sub_ident ident;
int interface; int interface;
@ -282,6 +287,9 @@ static void icarus_initialise(struct cgpu_info *icarus, int baud)
case IDENT_CMR2: case IDENT_CMR2:
usb_set_pps(icarus, BLT_PREF_PACKET); usb_set_pps(icarus, BLT_PREF_PACKET);
if (ident == IDENT_CMR2) // Chip hack
interface++;
// Reset // Reset
transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_RESET, transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_RESET,
interface, C_RESET); interface, C_RESET);
@ -403,6 +411,8 @@ static void icarus_initialise(struct cgpu_info *icarus, int baud)
quit(1, "icarus_intialise() called with invalid %s cgid %i ident=%d", quit(1, "icarus_intialise() called with invalid %s cgid %i ident=%d",
icarus->drv->name, icarus->cgminer_id, ident); icarus->drv->name, icarus->cgminer_id, ident);
} }
info->initialised = true;
} }
static void rev(unsigned char *s, size_t l) static void rev(unsigned char *s, size_t l)
@ -537,11 +547,12 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
case IDENT_AMU: case IDENT_AMU:
info->Hs = ASICMINERUSB_HASH_TIME; info->Hs = ASICMINERUSB_HASH_TIME;
break; break;
// TODO: ?
case IDENT_CMR1: case IDENT_CMR1:
case IDENT_CMR2:
info->Hs = CAIRNSMORE1_HASH_TIME; info->Hs = CAIRNSMORE1_HASH_TIME;
break; break;
case IDENT_CMR2:
info->Hs = CAIRNSMORE2_HASH_TIME;
break;
default: default:
quit(1, "Icarus get_options() called with invalid %s ident=%d", quit(1, "Icarus get_options() called with invalid %s ident=%d",
icarus->drv->name, ident); icarus->drv->name, ident);
@ -701,13 +712,16 @@ static void get_options(int this_option_offset, struct cgpu_info *icarus, int *b
*work_division = 1; *work_division = 1;
*fpga_count = 1; *fpga_count = 1;
break; break;
// TODO: ?
case IDENT_CMR1: case IDENT_CMR1:
case IDENT_CMR2:
*baud = ICARUS_IO_SPEED; *baud = ICARUS_IO_SPEED;
*work_division = 2; *work_division = 2;
*fpga_count = 2; *fpga_count = 2;
break; break;
case IDENT_CMR2:
*baud = ICARUS_IO_SPEED;
*work_division = 1;
*fpga_count = 1;
break;
default: default:
quit(1, "Icarus get_options() called with invalid %s ident=%d", quit(1, "Icarus get_options() called with invalid %s ident=%d",
icarus->drv->name, ident); icarus->drv->name, ident);
@ -795,6 +809,11 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
hex2bin(ob_bin, golden_ob, sizeof(ob_bin)); hex2bin(ob_bin, golden_ob, sizeof(ob_bin));
info = (struct ICARUS_INFO *)calloc(1, sizeof(struct ICARUS_INFO));
if (unlikely(!info))
quit(1, "Failed to malloc ICARUS_INFO");
icarus->device_data = (void *)info;
tries = 2; tries = 2;
ok = false; ok = false;
while (!ok && tries-- > 0) { while (!ok && tries-- > 0) {
@ -844,15 +863,6 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
applog(LOG_DEBUG, "%s%d: Init baud=%d work_division=%d fpga_count=%d", applog(LOG_DEBUG, "%s%d: Init baud=%d work_division=%d fpga_count=%d",
icarus->drv->name, icarus->device_id, baud, work_division, fpga_count); icarus->drv->name, icarus->device_id, baud, work_division, fpga_count);
info = (struct ICARUS_INFO *)malloc(sizeof(struct ICARUS_INFO));
if (unlikely(!info))
quit(1, "Failed to malloc ICARUS_INFO");
icarus->device_data = (void *)info;
// Initialise everything to zero for a new device
memset(info, 0, sizeof(struct ICARUS_INFO));
info->baud = baud; info->baud = baud;
info->work_division = work_division; info->work_division = work_division;
info->fpga_count = fpga_count; info->fpga_count = fpga_count;
@ -863,11 +873,46 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
set_timing_mode(this_option_offset, icarus); set_timing_mode(this_option_offset, icarus);
if (usb_ident(icarus) == IDENT_CMR2) {
int i;
for (i = 1; i < icarus->usbdev->found->intinfo_count; i++) {
struct cgpu_info *cgtmp;
struct ICARUS_INFO *intmp;
cgtmp = usb_init_intinfo(icarus, i);
if (!cgtmp) {
applog(LOG_ERR, "%s%d: Init failed initinfo %d",
icarus->drv->name, icarus->device_id, i);
continue;
}
cgtmp->usbinfo.usbstat = USB_NOSTAT;
if (!add_cgpu(cgtmp)) {
usb_uninit(cgtmp);
continue;
}
update_usb_stats(cgtmp);
intmp = (struct ICARUS_INFO *)malloc(sizeof(struct ICARUS_INFO));
if (unlikely(!intmp))
quit(1, "Failed2 to malloc ICARUS_INFO");
cgtmp->device_data = (void *)intmp;
// Initialise everything to match
memcpy(intmp, info, sizeof(struct ICARUS_INFO));
}
}
return true; return true;
unshin: unshin:
usb_uninit(icarus); usb_uninit(icarus);
free(info);
icarus->device_data = NULL;
shin: shin:
@ -917,6 +962,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
if (icarus->usbinfo.nodev) if (icarus->usbinfo.nodev)
return -1; return -1;
if (!info->initialised)
icarus_initialise(icarus, info->baud);
elapsed.tv_sec = elapsed.tv_usec = 0; elapsed.tv_sec = elapsed.tv_usec = 0;
memset(ob_bin, 0, sizeof(ob_bin)); memset(ob_bin, 0, sizeof(ob_bin));

564
usbutils.c

@ -25,6 +25,22 @@
#define NOCONTROLDEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \ #define NOCONTROLDEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \
(err) == LIBUSB_ERROR_OTHER) (err) == LIBUSB_ERROR_OTHER)
/*
* WARNING - these assume DEVLOCK(cgpu, pstate) is called first and
* DEVUNLOCK(cgpu, pstate) in called in the same function with the same pstate
* given to DEVLOCK.
* You must call DEVUNLOCK(cgpu, pstate) before exiting the function or it will leave
* the thread Cancelability unrestored
*/
#define DEVLOCK(cgpu, _pth_state) do { \
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &_pth_state); \
wr_lock(cgpu->usbinfo.devlock); \
} while (0)
#define DEVUNLOCK(cgpu, _pth_state) do { \
wr_unlock(cgpu->usbinfo.devlock); \
pthread_setcancelstate(_pth_state, NULL); \
} while (0)
#ifdef USE_BFLSC #ifdef USE_BFLSC
#define DRV_BFLSC 1 #define DRV_BFLSC 1
@ -70,74 +86,136 @@
#define USB_READ_MINPOLL 40 #define USB_READ_MINPOLL 40
#define USB_EPS(_intx, _epinfosx) { \
.interface = _intx, \
.epinfo_count = ARRAY_SIZE(_epinfosx), \
.epinfos = _epinfosx \
}
#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_endpoints bas_eps[] = { static struct usb_epinfo bas_epinfos[] = {
{ 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 }
}; };
static struct usb_intinfo bas_ints[] = {
USB_EPS(0, bas_epinfos)
};
#endif #endif
#ifdef USE_BITFORCE #ifdef USE_BITFORCE
// 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_endpoints bfl_eps[] = { static struct usb_epinfo bfl_epinfos[] = {
{ 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 }
}; };
static struct usb_intinfo bfl_ints[] = {
USB_EPS(0, bfl_epinfos)
};
#endif #endif
#ifdef USE_MODMINER #ifdef USE_MODMINER
static struct usb_endpoints mmq_eps[] = { static struct usb_epinfo mmq_epinfos[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(3), 0 } { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(3), 0 }
}; };
static struct usb_intinfo mmq_ints[] = {
USB_EPS(1, mmq_epinfos)
};
#endif #endif
#ifdef USE_AVALON #ifdef USE_AVALON
static struct usb_endpoints ava_eps[] = { static struct usb_epinfo ava_epinfos[] = {
{ 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 }
}; };
static struct usb_intinfo ava_ints[] = {
USB_EPS(0, ava_epinfos)
};
#endif #endif
#ifdef USE_ICARUS #ifdef USE_ICARUS
static struct usb_endpoints ica_eps[] = { static struct usb_epinfo ica_epinfos[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 }
}; };
static struct usb_endpoints amu_eps[] = {
static struct usb_intinfo ica_ints[] = {
USB_EPS(0, ica_epinfos)
};
static struct usb_epinfo amu_epinfos[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(1), 0 } { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(1), 0 }
}; };
static struct usb_endpoints llt_eps[] = {
static struct usb_intinfo amu_ints[] = {
USB_EPS(0, amu_epinfos)
};
static struct usb_epinfo llt_epinfos[] = {
{ 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 }
}; };
static struct usb_endpoints cmr1_eps[] = {
static struct usb_intinfo llt_ints[] = {
USB_EPS(0, llt_epinfos)
};
static struct usb_epinfo cmr1_epinfos[] = {
{ 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 }
/* };
Interface 1
static struct usb_intinfo cmr1_ints[] = {
USB_EPS(0, cmr1_epinfos)
};
static struct usb_epinfo cmr2_epinfos0[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 }
};
#ifndef WIN32
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 },
};
Interface 2 static struct usb_epinfo cmr2_epinfos2[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(5), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(5), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(6), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(6), 0 },
};
Interface 3 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 }
*/
}; };
static struct usb_endpoints cmr2_eps[] = { #endif
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } static struct usb_intinfo cmr2_ints[] = {
USB_EPS(0, cmr2_epinfos0)
#ifndef WIN32
,
USB_EPS(1, cmr2_epinfos1),
USB_EPS(2, cmr2_epinfos2),
USB_EPS(3, cmr2_epinfos3)
#endif
}; };
#endif #endif
#define IDVENDOR_FTDI 0x0403 #define IDVENDOR_FTDI 0x0403
#define INTINFO(_ints) \
.which_intinfo = 0, \
.intinfo_count = ARRAY_SIZE(_ints), \
.intinfos = _ints
#define USBEP(_usbdev, _epinfo) (_usbdev->found->intinfos[_usbdev->found->which_intinfo].epinfos[_epinfo].ep)
#define FOUNDIF(_found) (_found->intinfos[_found->which_intinfo].interface)
#define USBIF(_usbdev) FOUNDIF(_usbdev->found)
// 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[] = {
#ifdef USE_BFLSC #ifdef USE_BFLSC
@ -149,13 +227,10 @@ static struct usb_find_devices find_dev[] = {
.idProduct = 0x6014, .idProduct = 0x6014,
//.iManufacturer = "Butterfly Labs", //.iManufacturer = "Butterfly Labs",
.iProduct = "BitFORCE SHA256 SC", .iProduct = "BitFORCE SHA256 SC",
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = BFLSC_TIMEOUT_MS, .timeout = BFLSC_TIMEOUT_MS,
.latency = LATENCY_STD, .latency = LATENCY_STD,
.epcount = ARRAY_SIZE(bas_eps), INTINFO(bas_ints) },
.eps = bas_eps },
#endif #endif
#ifdef USE_BITFORCE #ifdef USE_BITFORCE
{ {
@ -166,13 +241,10 @@ static struct usb_find_devices find_dev[] = {
.idProduct = 0x6014, .idProduct = 0x6014,
.iManufacturer = "Butterfly Labs Inc.", .iManufacturer = "Butterfly Labs Inc.",
.iProduct = "BitFORCE SHA256", .iProduct = "BitFORCE SHA256",
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = BITFORCE_TIMEOUT_MS, .timeout = BITFORCE_TIMEOUT_MS,
.latency = LATENCY_STD, .latency = LATENCY_STD,
.epcount = ARRAY_SIZE(bfl_eps), INTINFO(bfl_ints) },
.eps = bfl_eps },
#endif #endif
#ifdef USE_MODMINER #ifdef USE_MODMINER
{ {
@ -181,13 +253,10 @@ static struct usb_find_devices find_dev[] = {
.ident = IDENT_MMQ, .ident = IDENT_MMQ,
.idVendor = 0x1fc9, .idVendor = 0x1fc9,
.idProduct = 0x0003, .idProduct = 0x0003,
.kernel = 0,
.config = 1, .config = 1,
.interface = 1,
.timeout = MODMINER_TIMEOUT_MS, .timeout = MODMINER_TIMEOUT_MS,
.latency = LATENCY_UNUSED, .latency = LATENCY_UNUSED,
.epcount = ARRAY_SIZE(mmq_eps), INTINFO(mmq_ints) },
.eps = mmq_eps },
#endif #endif
#ifdef USE_AVALON #ifdef USE_AVALON
{ {
@ -198,26 +267,20 @@ static struct usb_find_devices find_dev[] = {
.idProduct = 0x6001, .idProduct = 0x6001,
.iManufacturer = "Burnin Electronics", .iManufacturer = "Burnin Electronics",
.iProduct = "BitBurner", .iProduct = "BitBurner",
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = AVALON_TIMEOUT_MS, .timeout = AVALON_TIMEOUT_MS,
.latency = 10, .latency = 10,
.epcount = ARRAY_SIZE(ava_eps), INTINFO(ava_ints) },
.eps = ava_eps },
{ {
.drv = DRV_AVALON, .drv = DRV_AVALON,
.name = "AVA", .name = "AVA",
.ident = IDENT_AVA, .ident = IDENT_AVA,
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x6001, .idProduct = 0x6001,
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = AVALON_TIMEOUT_MS, .timeout = AVALON_TIMEOUT_MS,
.latency = 10, .latency = 10,
.epcount = ARRAY_SIZE(ava_eps), INTINFO(ava_ints) },
.eps = ava_eps },
#endif #endif
#ifdef USE_ICARUS #ifdef USE_ICARUS
{ {
@ -226,26 +289,20 @@ static struct usb_find_devices find_dev[] = {
.ident = IDENT_ICA, .ident = IDENT_ICA,
.idVendor = 0x067b, .idVendor = 0x067b,
.idProduct = 0x2303, .idProduct = 0x2303,
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.latency = LATENCY_UNUSED, .latency = LATENCY_UNUSED,
.epcount = ARRAY_SIZE(ica_eps), INTINFO(ica_ints) },
.eps = ica_eps },
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
.name = "AMU", .name = "AMU",
.ident = IDENT_AMU, .ident = IDENT_AMU,
.idVendor = 0x10c4, .idVendor = 0x10c4,
.idProduct = 0xea60, .idProduct = 0xea60,
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.latency = LATENCY_UNUSED, .latency = LATENCY_UNUSED,
.epcount = ARRAY_SIZE(amu_eps), INTINFO(amu_ints) },
.eps = amu_eps },
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
.name = "BLT", .name = "BLT",
@ -253,13 +310,10 @@ static struct usb_find_devices find_dev[] = {
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x6001, .idProduct = 0x6001,
.iProduct = "FT232R USB UART", .iProduct = "FT232R USB UART",
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.latency = LATENCY_STD, .latency = LATENCY_STD,
.epcount = ARRAY_SIZE(llt_eps), INTINFO(llt_ints) },
.eps = llt_eps },
// For any that don't match the above "BLT" // For any that don't match the above "BLT"
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
@ -267,41 +321,32 @@ static struct usb_find_devices find_dev[] = {
.ident = IDENT_LLT, .ident = IDENT_LLT,
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x6001, .idProduct = 0x6001,
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.latency = LATENCY_STD, .latency = LATENCY_STD,
.epcount = ARRAY_SIZE(llt_eps), INTINFO(llt_ints) },
.eps = llt_eps },
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
.name = "CMR", .name = "CMR",
.ident = IDENT_CMR1, .ident = IDENT_CMR1,
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x8350, .idProduct = 0x6014,
.iProduct = "Cairnsmore1", .iProduct = "Cairnsmore1",
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.latency = LATENCY_STD, .latency = LATENCY_STD,
.epcount = ARRAY_SIZE(cmr1_eps), INTINFO(cmr1_ints) },
.eps = cmr1_eps },
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
.name = "CMR", .name = "CMR",
.ident = IDENT_CMR2, .ident = IDENT_CMR2,
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x6014, .idProduct = 0x8350,
.iProduct = "Cairnsmore1", .iProduct = "Cairnsmore1",
.kernel = 0,
.config = 1, .config = 1,
.interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.latency = LATENCY_STD, .latency = LATENCY_STD,
.epcount = ARRAY_SIZE(cmr2_eps), INTINFO(cmr2_ints) },
.eps = cmr2_eps },
#endif #endif
#ifdef USE_ZTEX #ifdef USE_ZTEX
// This is here so cgminer -n shows them // This is here so cgminer -n shows them
@ -312,15 +357,14 @@ static struct usb_find_devices find_dev[] = {
.ident = IDENT_ZTX, .ident = IDENT_ZTX,
.idVendor = 0x221a, .idVendor = 0x221a,
.idProduct = 0x0100, .idProduct = 0x0100,
.kernel = 0,
.config = 1, .config = 1,
.interface = 1,
.timeout = 100, .timeout = 100,
.latency = LATENCY_UNUSED, .latency = LATENCY_UNUSED,
.epcount = 0, .which_intinfo = 0,
.eps = NULL }, .intinfo_count = 0,
.intinfos = NULL },
#endif #endif
{ DRV_LAST, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, NULL } { DRV_LAST, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL }
}; };
#ifdef USE_BFLSC #ifdef USE_BFLSC
@ -1340,7 +1384,8 @@ 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);
free(cgusb->descriptor); if (cgusb->descriptor)
free(cgusb->descriptor);
free(cgusb->found); free(cgusb->found);
@ -1352,7 +1397,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);
@ -1361,14 +1406,28 @@ 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 (!libusb_release_interface(cgpu->usbdev->handle, cgpu->usbdev->found->interface)) {
if (cgpu->usbdev->handle) {
libusb_release_interface(cgpu->usbdev->handle, USBIF(cgpu->usbdev));
cg_wlock(&cgusb_fd_lock); cg_wlock(&cgusb_fd_lock);
libusb_close(cgpu->usbdev->handle); libusb_close(cgpu->usbdev->handle);
cgpu->usbdev->handle = NULL;
cg_wunlock(&cgusb_fd_lock); cg_wunlock(&cgusb_fd_lock);
} }
cgpu->usbdev = free_cgusb(cgpu->usbdev); cgpu->usbdev = free_cgusb(cgpu->usbdev);
} }
void usb_uninit(struct cgpu_info *cgpu)
{
int pstate;
DEVLOCK(cgpu, pstate);
_usb_uninit(cgpu);
DEVUNLOCK(cgpu, pstate);
}
/* /*
* N.B. this is always called inside * N.B. this is always called inside
* DEVLOCK(cgpu, pstate); * DEVLOCK(cgpu, pstate);
@ -1377,7 +1436,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 i; int which_intinfo, 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);
@ -1410,16 +1469,24 @@ static void release_cgpu(struct cgpu_info *cgpu)
} }
} }
usb_uninit(cgpu); which_intinfo = cgpu->usbdev->found->which_intinfo;
_usb_uninit(cgpu);
cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); if (which_intinfo == 0)
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);
@ -1436,6 +1503,75 @@ 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)
* 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; return copy;
} }
@ -1480,23 +1616,6 @@ struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devloc
#define USB_INIT_OK 1 #define USB_INIT_OK 1
#define USB_INIT_IGNORE 2 #define USB_INIT_IGNORE 2
/*
* WARNING - these assume DEVLOCK(cgpu, pstate) is called first and
* DEVUNLOCK(cgpu, pstate) in called in the same function with the same pstate
* given to DEVLOCK.
* You must call DEVUNLOCK(cgpu, pstate) before exiting the function or it will leave
* the thread Cancelability unrestored
*/
#define DEVLOCK(cgpu, _pth_state) do { \
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &_pth_state); \
wr_lock(cgpu->usbinfo.devlock); \
} while (0)
#define DEVUNLOCK(cgpu, _pth_state) do { \
wr_unlock(cgpu->usbinfo.devlock); \
pthread_setcancelstate(_pth_state, NULL); \
} while (0)
static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found)
{ {
struct cg_usb_device *cgusb = NULL; struct cg_usb_device *cgusb = NULL;
@ -1506,7 +1625,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
unsigned char strbuf[STRBUFLEN+1]; unsigned char strbuf[STRBUFLEN+1];
char devpath[32]; char devpath[32];
char devstr[STRBUFLEN+1]; char devstr[STRBUFLEN+1];
int err, i, j, k, pstate; int err, ifinfo, epinfo, alt, epnum, pstate;
int bad = USB_INIT_FAIL; int bad = USB_INIT_FAIL;
int cfg; int cfg;
@ -1515,9 +1634,16 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
cgpu->usbinfo.bus_number = libusb_get_bus_number(dev); cgpu->usbinfo.bus_number = libusb_get_bus_number(dev);
cgpu->usbinfo.device_address = libusb_get_device_address(dev); cgpu->usbinfo.device_address = libusb_get_device_address(dev);
snprintf(devpath, sizeof(devpath), "%d:%d", if (found->intinfo_count > 1) {
(int)(cgpu->usbinfo.bus_number), snprintf(devpath, sizeof(devpath), "%d:%d-i%d",
(int)(cgpu->usbinfo.device_address)); (int)(cgpu->usbinfo.bus_number),
(int)(cgpu->usbinfo.device_address),
FOUNDIF(found));
} else {
snprintf(devpath, sizeof(devpath), "%d:%d",
(int)(cgpu->usbinfo.bus_number),
(int)(cgpu->usbinfo.device_address));
}
cgpu->device_path = strdup(devpath); cgpu->device_path = strdup(devpath);
@ -1574,17 +1700,17 @@ 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, found->kernel) == 1) { if (libusb_kernel_driver_active(cgusb->handle, FOUNDIF(found)) == 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, found->kernel); 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 successfully %s", "USB init, kernel detached interface %d successfully %s",
devstr); FOUNDIF(found), devstr);
} else { } else {
applog(LOG_WARNING, applog(LOG_WARNING,
"USB init, kernel detach failed, err %d in use? %s", "USB init, kernel detach interface %d failed, err %d in use? %s",
err, devstr); FOUNDIF(found), err, devstr);
goto cldame; goto cldame;
} }
} }
@ -1662,55 +1788,66 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
goto cldame; goto cldame;
} }
if ((int)(config->bNumInterfaces) <= found->interface) { int imax = -1;
applog(LOG_DEBUG, "USB init bNumInterfaces <= interface %s", for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++)
devstr); if (found->intinfos[ifinfo].interface > imax)
imax = found->intinfos[ifinfo].interface;
if ((int)(config->bNumInterfaces) <= imax) {
applog(LOG_DEBUG, "USB init bNumInterfaces %d <= interface max %d for %s",
(int)(config->bNumInterfaces), imax, devstr);
goto cldame; goto cldame;
} }
for (i = 0; i < found->epcount; i++) for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++)
found->eps[i].found = false; for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++)
found->intinfos[ifinfo].epinfos[epinfo].found = false;
for (i = 0; i < config->interface[found->interface].num_altsetting; i++) {
idesc = &(config->interface[found->interface].altsetting[i]); for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) {
for (j = 0; j < (int)(idesc->bNumEndpoints); j++) { int interface = found->intinfos[ifinfo].interface;
epdesc = &(idesc->endpoint[j]); for (alt = 0; alt < config->interface[interface].num_altsetting; alt++) {
for (k = 0; k < found->epcount; k++) { idesc = &(config->interface[interface].altsetting[alt]);
if (!found->eps[k].found) { for (epnum = 0; epnum < (int)(idesc->bNumEndpoints); epnum++) {
if (epdesc->bmAttributes == found->eps[k].att struct usb_epinfo *epinfos = found->intinfos[ifinfo].epinfos;
&& epdesc->wMaxPacketSize >= found->eps[k].size epdesc = &(idesc->endpoint[epnum]);
&& epdesc->bEndpointAddress == found->eps[k].ep) { for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++) {
found->eps[k].found = true; if (!epinfos[epinfo].found) {
found->wMaxPacketSize = epdesc->wMaxPacketSize; if (epdesc->bmAttributes == epinfos[epinfo].att
break; && epdesc->wMaxPacketSize >= epinfos[epinfo].size
&& epdesc->bEndpointAddress == epinfos[epinfo].ep) {
epinfos[epinfo].found = true;
// TODO: it's an ep (not device) attribute
found->wMaxPacketSize = epdesc->wMaxPacketSize;
break;
}
} }
} }
} }
} }
} }
for (i = 0; i < found->epcount; i++) { for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++)
if (found->eps[i].found == false) { for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++)
applog(LOG_DEBUG, "USB init found == false %s", if (found->intinfos[ifinfo].epinfos[epinfo].found == false) {
devstr); applog(LOG_DEBUG, "USB init found (%d,%d) == false %s",
goto cldame; ifinfo, epinfo, devstr);
} goto cldame;
} }
err = libusb_claim_interface(cgusb->handle, found->interface); err = libusb_claim_interface(cgusb->handle, FOUNDIF(found));
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",
found->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",
found->interface, err, devstr); FOUNDIF(found), err, devstr);
} }
goto cldame; goto reldame;
} }
cfg = -1; cfg = -1;
@ -1777,12 +1914,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
reldame: reldame:
libusb_release_interface(cgusb->handle, found->interface); libusb_release_interface(cgusb->handle, FOUNDIF(found));
cldame: cldame:
cg_wlock(&cgusb_fd_lock); cg_wlock(&cgusb_fd_lock);
libusb_close(cgusb->handle); libusb_close(cgusb->handle);
cgusb->handle = NULL;
cg_wunlock(&cgusb_fd_lock); cg_wunlock(&cgusb_fd_lock);
dame: dame:
@ -1798,6 +1936,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-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;
@ -2356,7 +2632,7 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle,
return err; return err;
} }
int _usb_read(struct cgpu_info *cgpu, int ep, 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 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;
@ -2384,7 +2660,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
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),ep=%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), ep, 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),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));
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);
@ -2438,7 +2714,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
} }
} }
err = usb_bulk_transfer(usbdev->handle, err = usb_bulk_transfer(usbdev->handle,
usbdev->found->eps[ep].ep, USBEP(usbdev, 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);
@ -2542,7 +2818,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
} }
} }
err = usb_bulk_transfer(usbdev->handle, err = usb_bulk_transfer(usbdev->handle,
usbdev->found->eps[ep].ep, ptr, USBEP(usbdev, 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);
@ -2629,7 +2905,7 @@ out_unlock:
return err; return err;
} }
int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds cmd) int _usb_write(struct cgpu_info *cgpu, 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;
@ -2640,7 +2916,7 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
DEVLOCK(cgpu, pstate); DEVLOCK(cgpu, pstate);
USBDEBUG("USB debug: _usb_write(%s (nodev=%s),ep=%d,buf='%s',bufsiz=%zu,proc=%p,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), ep, (char *)str_text(buf), bufsiz, processed, timeout, usb_cmdname(cmd)); 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));
*processed = 0; *processed = 0;
@ -2683,7 +2959,7 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
usbdev->last_write_siz = bufsiz; usbdev->last_write_siz = bufsiz;
} }
err = usb_bulk_transfer(usbdev->handle, err = usb_bulk_transfer(usbdev->handle,
usbdev->found->eps[ep].ep, USBEP(usbdev, 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);
@ -2921,7 +3197,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,
cgpu->usbdev->found->interface, USBIF(cgpu->usbdev),
NULL, 0, DEVTIMEOUT, C_LATENCY); NULL, 0, DEVTIMEOUT, C_LATENCY);
} }
@ -3048,7 +3324,7 @@ int usb_interface(struct cgpu_info *cgpu)
DEVLOCK(cgpu, pstate); DEVLOCK(cgpu, pstate);
if (cgpu->usbdev) if (cgpu->usbdev)
interface = cgpu->usbdev->found->interface; interface = USBIF(cgpu->usbdev);
DEVUNLOCK(cgpu, pstate); DEVUNLOCK(cgpu, pstate);

20
usbutils.h

@ -109,18 +109,24 @@
// Use the device defined timeout // Use the device defined timeout
#define DEVTIMEOUT 0 #define DEVTIMEOUT 0
// For endpoints defined in usb_find_devices.eps, // For endpoints defined in usb_find_devices.intinfos.epinfos,
// the first two must be the default IN and OUT // the first two must be the default IN and OUT and both must always exist
#define DEFAULT_EP_IN 0 #define DEFAULT_EP_IN 0
#define DEFAULT_EP_OUT 1 #define DEFAULT_EP_OUT 1
struct usb_endpoints { struct usb_epinfo {
uint8_t att; uint8_t att;
uint16_t size; uint16_t size;
unsigned char ep; unsigned char ep;
bool found; bool found;
}; };
struct usb_intinfo {
int interface;
int epinfo_count;
struct usb_epinfo *epinfos;
};
enum sub_ident { enum sub_ident {
IDENT_UNK = 0, IDENT_UNK = 0,
IDENT_BAJ, IDENT_BAJ,
@ -148,14 +154,13 @@ struct usb_find_devices {
uint16_t idProduct; uint16_t idProduct;
char *iManufacturer; char *iManufacturer;
char *iProduct; char *iProduct;
int kernel;
int config; int config;
int interface;
unsigned int timeout; unsigned int timeout;
uint16_t wMaxPacketSize; uint16_t wMaxPacketSize;
uint16_t latency; uint16_t latency;
int epcount; int which_intinfo;
struct usb_endpoints *eps; int intinfo_count;
struct usb_intinfo *intinfos;
}; };
/* Latency is set to 32ms to prevent a transfer ever being more than 512 bytes /* Latency is set to 32ms to prevent a transfer ever being more than 512 bytes
@ -330,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