|
@@ -25,7 +25,23 @@
|
|
|
#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
|
|
|
#endif
|
|
#endif
|
|
@@ -74,74 +90,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[] = {
|
|
|
|
|
- { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 },
|
|
|
|
|
- { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 }
|
|
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+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
|
|
@@ -153,13 +231,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),
|
|
|
|
|
- .eps = bas_eps },
|
|
|
|
|
|
|
+ INTINFO(bas_ints) },
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef USE_BITFORCE
|
|
#ifdef USE_BITFORCE
|
|
|
{
|
|
{
|
|
@@ -170,13 +245,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),
|
|
|
|
|
- .eps = bfl_eps },
|
|
|
|
|
|
|
+ INTINFO(bfl_ints) },
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef USE_MODMINER
|
|
#ifdef USE_MODMINER
|
|
|
{
|
|
{
|
|
@@ -185,13 +257,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),
|
|
|
|
|
- .eps = mmq_eps },
|
|
|
|
|
|
|
+ INTINFO(mmq_ints) },
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef USE_AVALON
|
|
#ifdef USE_AVALON
|
|
|
{
|
|
{
|
|
@@ -202,26 +271,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),
|
|
|
|
|
- .eps = ava_eps },
|
|
|
|
|
|
|
+ INTINFO(ava_ints) },
|
|
|
{
|
|
{
|
|
|
.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),
|
|
|
|
|
- .eps = ava_eps },
|
|
|
|
|
|
|
+ INTINFO(ava_ints) },
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef USE_HASHFAST
|
|
#ifdef USE_HASHFAST
|
|
|
{
|
|
{
|
|
@@ -237,26 +300,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),
|
|
|
|
|
- .eps = ica_eps },
|
|
|
|
|
|
|
+ INTINFO(ica_ints) },
|
|
|
{
|
|
{
|
|
|
.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),
|
|
|
|
|
- .eps = amu_eps },
|
|
|
|
|
|
|
+ INTINFO(amu_ints) },
|
|
|
{
|
|
{
|
|
|
.drv = DRV_ICARUS,
|
|
.drv = DRV_ICARUS,
|
|
|
.name = "BLT",
|
|
.name = "BLT",
|
|
@@ -264,13 +321,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),
|
|
|
|
|
- .eps = llt_eps },
|
|
|
|
|
|
|
+ INTINFO(llt_ints) },
|
|
|
// For any that don't match the above "BLT"
|
|
// For any that don't match the above "BLT"
|
|
|
{
|
|
{
|
|
|
.drv = DRV_ICARUS,
|
|
.drv = DRV_ICARUS,
|
|
@@ -278,41 +332,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),
|
|
|
|
|
- .eps = llt_eps },
|
|
|
|
|
|
|
+ INTINFO(llt_ints) },
|
|
|
{
|
|
{
|
|
|
.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),
|
|
|
|
|
- .eps = cmr1_eps },
|
|
|
|
|
|
|
+ INTINFO(cmr1_ints) },
|
|
|
{
|
|
{
|
|
|
.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),
|
|
|
|
|
- .eps = cmr2_eps },
|
|
|
|
|
|
|
+ INTINFO(cmr2_ints) },
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef USE_ZTEX
|
|
#ifdef USE_ZTEX
|
|
|
// This is here so cgminer -n shows them
|
|
// This is here so cgminer -n shows them
|
|
@@ -323,15 +368,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,
|
|
|
|
|
- .eps = NULL },
|
|
|
|
|
|
|
+ .which_intinfo = 0,
|
|
|
|
|
+ .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
|
|
@@ -1375,7 +1419,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);
|
|
|
|
|
|
|
@@ -1387,7 +1432,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);
|
|
@@ -1396,14 +1441,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);
|
|
@@ -1412,7 +1471,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);
|
|
@@ -1445,16 +1504,24 @@ static void release_cgpu(struct cgpu_info *cgpu)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- usb_uninit(cgpu);
|
|
|
|
|
-
|
|
|
|
|
- cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address);
|
|
|
|
|
|
|
+ which_intinfo = cgpu->usbdev->found->which_intinfo;
|
|
|
|
|
+ _usb_uninit(cgpu);
|
|
|
|
|
+ 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);
|
|
|
|
|
|
|
@@ -1471,6 +1538,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;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1515,23 +1651,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;
|
|
@@ -1541,7 +1660,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;
|
|
|
|
|
|
|
@@ -1550,9 +1669,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",
|
|
|
|
|
- (int)(cgpu->usbinfo.bus_number),
|
|
|
|
|
- (int)(cgpu->usbinfo.device_address));
|
|
|
|
|
|
|
+ if (found->intinfo_count > 1) {
|
|
|
|
|
+ snprintf(devpath, sizeof(devpath), "%d:%d-i%d",
|
|
|
|
|
+ (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);
|
|
|
|
|
|
|
@@ -1609,17 +1735,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",
|
|
|
|
|
- devstr);
|
|
|
|
|
|
|
+ "USB init, kernel detached interface %d successfully %s",
|
|
|
|
|
+ FOUNDIF(found), devstr);
|
|
|
} else {
|
|
} else {
|
|
|
applog(LOG_WARNING,
|
|
applog(LOG_WARNING,
|
|
|
- "USB init, kernel detach failed, err %d in use? %s",
|
|
|
|
|
- err, devstr);
|
|
|
|
|
|
|
+ "USB init, kernel detach interface %d failed, err %d in use? %s",
|
|
|
|
|
+ FOUNDIF(found), err, devstr);
|
|
|
goto cldame;
|
|
goto cldame;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1697,55 +1823,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) {
|
|
|
|
|
- applog(LOG_DEBUG, "USB init bNumInterfaces <= interface %s",
|
|
|
|
|
- devstr);
|
|
|
|
|
|
|
+ int imax = -1;
|
|
|
|
|
+ for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++)
|
|
|
|
|
+ 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++)
|
|
|
|
|
- found->eps[i].found = false;
|
|
|
|
|
-
|
|
|
|
|
- for (i = 0; i < config->interface[found->interface].num_altsetting; i++) {
|
|
|
|
|
- idesc = &(config->interface[found->interface].altsetting[i]);
|
|
|
|
|
- for (j = 0; j < (int)(idesc->bNumEndpoints); j++) {
|
|
|
|
|
- epdesc = &(idesc->endpoint[j]);
|
|
|
|
|
- for (k = 0; k < found->epcount; k++) {
|
|
|
|
|
- if (!found->eps[k].found) {
|
|
|
|
|
- if (epdesc->bmAttributes == found->eps[k].att
|
|
|
|
|
- && epdesc->wMaxPacketSize >= found->eps[k].size
|
|
|
|
|
- && epdesc->bEndpointAddress == found->eps[k].ep) {
|
|
|
|
|
- found->eps[k].found = true;
|
|
|
|
|
- found->wMaxPacketSize = epdesc->wMaxPacketSize;
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++)
|
|
|
|
|
+ for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++)
|
|
|
|
|
+ found->intinfos[ifinfo].epinfos[epinfo].found = false;
|
|
|
|
|
+
|
|
|
|
|
+ for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) {
|
|
|
|
|
+ int interface = found->intinfos[ifinfo].interface;
|
|
|
|
|
+ for (alt = 0; alt < config->interface[interface].num_altsetting; alt++) {
|
|
|
|
|
+ idesc = &(config->interface[interface].altsetting[alt]);
|
|
|
|
|
+ for (epnum = 0; epnum < (int)(idesc->bNumEndpoints); epnum++) {
|
|
|
|
|
+ struct usb_epinfo *epinfos = found->intinfos[ifinfo].epinfos;
|
|
|
|
|
+ epdesc = &(idesc->endpoint[epnum]);
|
|
|
|
|
+ for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++) {
|
|
|
|
|
+ if (!epinfos[epinfo].found) {
|
|
|
|
|
+ if (epdesc->bmAttributes == epinfos[epinfo].att
|
|
|
|
|
+ && 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++) {
|
|
|
|
|
- if (found->eps[i].found == false) {
|
|
|
|
|
- applog(LOG_DEBUG, "USB init found == false %s",
|
|
|
|
|
- devstr);
|
|
|
|
|
- goto cldame;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++)
|
|
|
|
|
+ for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++)
|
|
|
|
|
+ if (found->intinfos[ifinfo].epinfos[epinfo].found == false) {
|
|
|
|
|
+ applog(LOG_DEBUG, "USB init found (%d,%d) == false %s",
|
|
|
|
|
+ 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;
|
|
@@ -1812,12 +1949,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:
|
|
@@ -1833,6 +1971,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;
|
|
@@ -2391,7 +2667,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;
|
|
@@ -2419,7 +2695,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);
|
|
@@ -2473,7 +2749,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);
|
|
@@ -2516,7 +2792,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
|
|
|
// N.B. usbdev->buffer was emptied before the while() loop
|
|
// N.B. usbdev->buffer was emptied before the while() loop
|
|
|
if (usbdev->buffer && tot > (int)bufsiz) {
|
|
if (usbdev->buffer && tot > (int)bufsiz) {
|
|
|
usbdev->bufamt = tot - bufsiz;
|
|
usbdev->bufamt = tot - bufsiz;
|
|
|
- memcpy(usbdev->buffer, ptr + bufsiz, usbdev->bufamt);
|
|
|
|
|
|
|
+ memcpy(usbdev->buffer, usbbuf + bufsiz, usbdev->bufamt);
|
|
|
tot -= usbdev->bufamt;
|
|
tot -= usbdev->bufamt;
|
|
|
usbbuf[tot] = '\0';
|
|
usbbuf[tot] = '\0';
|
|
|
applog(LOG_ERR, "USB: %s%i read1 buffering %d extra bytes",
|
|
applog(LOG_ERR, "USB: %s%i read1 buffering %d extra bytes",
|
|
@@ -2577,7 +2853,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);
|
|
@@ -2664,7 +2940,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;
|
|
@@ -2675,7 +2951,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;
|
|
|
|
|
|
|
@@ -2718,7 +2994,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);
|
|
@@ -2956,7 +3232,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);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -3083,7 +3359,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);
|
|
|
|
|
|