@ -25,6 +25,22 @@
@@ -25,6 +25,22 @@
# define NOCONTROLDEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \
( 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
# define DRV_BFLSC 1
@ -74,74 +90,136 @@
@@ -74,74 +90,136 @@
# define USB_READ_MINPOLL 40
# define USB_EPS(_intx, _epinfosx) { \
. interface = _intx , \
. epinfo_count = ARRAY_SIZE ( _epinfosx ) , \
. epinfos = _epinfosx \
}
# ifdef USE_BFLSC
// 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_epinfo s [ ] = {
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPI ( 1 ) , 0 } ,
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPO ( 2 ) , 0 }
} ;
static struct usb_intinfo bas_ints [ ] = {
USB_EPS ( 0 , bas_epinfos )
} ;
# endif
# ifdef USE_BITFORCE
// N.B. transfer size is 512 with USB2.0, but only 64 with USB1.1
static struct usb_endpoints bfl_ep s [ ] = {
static struct usb_epinfo bfl_epinfo s [ ] = {
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPI ( 1 ) , 0 } ,
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPO ( 2 ) , 0 }
} ;
static struct usb_intinfo bfl_ints [ ] = {
USB_EPS ( 0 , bfl_epinfos )
} ;
# endif
# ifdef USE_MODMINER
static struct usb_endpoints mmq_eps [ ] = {
static struct usb_epinfo mmq_epinfo s [ ] = {
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPI ( 3 ) , 0 } ,
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPO ( 3 ) , 0 }
} ;
static struct usb_intinfo mmq_ints [ ] = {
USB_EPS ( 1 , mmq_epinfos )
} ;
# endif
# ifdef USE_AVALON
static struct usb_endpoints ava_eps [ ] = {
static struct usb_epinfo ava_epinfo s [ ] = {
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPI ( 1 ) , 0 } ,
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPO ( 2 ) , 0 }
} ;
static struct usb_intinfo ava_ints [ ] = {
USB_EPS ( 0 , ava_epinfos )
} ;
# endif
# ifdef USE_ICARUS
static struct usb_endpoints ica_eps [ ] = {
static struct usb_epinfo ica_epinfo s [ ] = {
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPI ( 3 ) , 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 , 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 , 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 , 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 , EPO ( 4 ) , 0 } ,
Interface 2
} ;
static struct usb_epinfo cmr2_epinfos2 [ ] = {
{ LIBUSB_TRANSFER_TYPE_BULK , 64 , EPI ( 5 ) , 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 , 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
# 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
static struct usb_find_devices find_dev [ ] = {
# ifdef USE_BFLSC
@ -153,13 +231,10 @@ static struct usb_find_devices find_dev[] = {
@@ -153,13 +231,10 @@ static struct usb_find_devices find_dev[] = {
. idProduct = 0x6014 ,
//.iManufacturer = "Butterfly Labs",
. iProduct = " BitFORCE SHA256 SC " ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = BFLSC_TIMEOUT_MS ,
. latency = LATENCY_STD ,
. epcount = ARRAY_SIZE ( bas_eps ) ,
. eps = bas_eps } ,
INTINFO ( bas_ints ) } ,
# endif
# ifdef USE_BITFORCE
{
@ -170,13 +245,10 @@ static struct usb_find_devices find_dev[] = {
@@ -170,13 +245,10 @@ static struct usb_find_devices find_dev[] = {
. idProduct = 0x6014 ,
. iManufacturer = " Butterfly Labs Inc. " ,
. iProduct = " BitFORCE SHA256 " ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = BITFORCE_TIMEOUT_MS ,
. latency = LATENCY_STD ,
. epcount = ARRAY_SIZE ( bfl_eps ) ,
. eps = bfl_eps } ,
INTINFO ( bfl_ints ) } ,
# endif
# ifdef USE_MODMINER
{
@ -185,13 +257,10 @@ static struct usb_find_devices find_dev[] = {
@@ -185,13 +257,10 @@ static struct usb_find_devices find_dev[] = {
. ident = IDENT_MMQ ,
. idVendor = 0x1fc9 ,
. idProduct = 0x0003 ,
. kernel = 0 ,
. config = 1 ,
. interface = 1 ,
. timeout = MODMINER_TIMEOUT_MS ,
. latency = LATENCY_UNUSED ,
. epcount = ARRAY_SIZE ( mmq_eps ) ,
. eps = mmq_eps } ,
INTINFO ( mmq_ints ) } ,
# endif
# ifdef USE_AVALON
{
@ -202,26 +271,20 @@ static struct usb_find_devices find_dev[] = {
@@ -202,26 +271,20 @@ static struct usb_find_devices find_dev[] = {
. idProduct = 0x6001 ,
. iManufacturer = " Burnin Electronics " ,
. iProduct = " BitBurner " ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = AVALON_TIMEOUT_MS ,
. latency = 10 ,
. epcount = ARRAY_SIZE ( ava_eps ) ,
. eps = ava_eps } ,
INTINFO ( ava_ints ) } ,
{
. drv = DRV_AVALON ,
. name = " AVA " ,
. ident = IDENT_AVA ,
. idVendor = IDVENDOR_FTDI ,
. idProduct = 0x6001 ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = AVALON_TIMEOUT_MS ,
. latency = 10 ,
. epcount = ARRAY_SIZE ( ava_eps ) ,
. eps = ava_eps } ,
INTINFO ( ava_ints ) } ,
# endif
# ifdef USE_HASHFAST
{
@ -237,26 +300,20 @@ static struct usb_find_devices find_dev[] = {
@@ -237,26 +300,20 @@ static struct usb_find_devices find_dev[] = {
. ident = IDENT_ICA ,
. idVendor = 0x067b ,
. idProduct = 0x2303 ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = ICARUS_TIMEOUT_MS ,
. latency = LATENCY_UNUSED ,
. epcount = ARRAY_SIZE ( ica_eps ) ,
. eps = ica_eps } ,
INTINFO ( ica_ints ) } ,
{
. drv = DRV_ICARUS ,
. name = " AMU " ,
. ident = IDENT_AMU ,
. idVendor = 0x10c4 ,
. idProduct = 0xea60 ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = ICARUS_TIMEOUT_MS ,
. latency = LATENCY_UNUSED ,
. epcount = ARRAY_SIZE ( amu_eps ) ,
. eps = amu_eps } ,
INTINFO ( amu_ints ) } ,
{
. drv = DRV_ICARUS ,
. name = " BLT " ,
@ -264,13 +321,10 @@ static struct usb_find_devices find_dev[] = {
@@ -264,13 +321,10 @@ static struct usb_find_devices find_dev[] = {
. idVendor = IDVENDOR_FTDI ,
. idProduct = 0x6001 ,
. iProduct = " FT232R USB UART " ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = ICARUS_TIMEOUT_MS ,
. latency = LATENCY_STD ,
. epcount = ARRAY_SIZE ( llt_eps ) ,
. eps = llt_eps } ,
INTINFO ( llt_ints ) } ,
// For any that don't match the above "BLT"
{
. drv = DRV_ICARUS ,
@ -278,41 +332,32 @@ static struct usb_find_devices find_dev[] = {
@@ -278,41 +332,32 @@ static struct usb_find_devices find_dev[] = {
. ident = IDENT_LLT ,
. idVendor = IDVENDOR_FTDI ,
. idProduct = 0x6001 ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = ICARUS_TIMEOUT_MS ,
. latency = LATENCY_STD ,
. epcount = ARRAY_SIZE ( llt_eps ) ,
. eps = llt_eps } ,
INTINFO ( llt_ints ) } ,
{
. drv = DRV_ICARUS ,
. name = " CMR " ,
. ident = IDENT_CMR1 ,
. idVendor = IDVENDOR_FTDI ,
. idProduct = 0x8350 ,
. idProduct = 0x6014 ,
. iProduct = " Cairnsmore1 " ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = ICARUS_TIMEOUT_MS ,
. latency = LATENCY_STD ,
. epcount = ARRAY_SIZE ( cmr1_eps ) ,
. eps = cmr1_eps } ,
INTINFO ( cmr1_ints ) } ,
{
. drv = DRV_ICARUS ,
. name = " CMR " ,
. ident = IDENT_CMR2 ,
. idVendor = IDVENDOR_FTDI ,
. idProduct = 0x6014 ,
. idProduct = 0x8350 ,
. iProduct = " Cairnsmore1 " ,
. kernel = 0 ,
. config = 1 ,
. interface = 0 ,
. timeout = ICARUS_TIMEOUT_MS ,
. latency = LATENCY_STD ,
. epcount = ARRAY_SIZE ( cmr2_eps ) ,
. eps = cmr2_eps } ,
INTINFO ( cmr2_ints ) } ,
# endif
# ifdef USE_ZTEX
// This is here so cgminer -n shows them
@ -323,15 +368,14 @@ static struct usb_find_devices find_dev[] = {
@@ -323,15 +368,14 @@ static struct usb_find_devices find_dev[] = {
. ident = IDENT_ZTX ,
. idVendor = 0x221a ,
. idProduct = 0x0100 ,
. kernel = 0 ,
. config = 1 ,
. interface = 1 ,
. timeout = 100 ,
. latency = LATENCY_UNUSED ,
. epcount = 0 ,
. eps = NULL } ,
. which_intinfo = 0 ,
. intinfo_count = 0 ,
. intinfos = NULL } ,
# 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
@ -1375,6 +1419,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
@@ -1375,6 +1419,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
if ( cgusb - > prod_string & & cgusb - > prod_string ! = BLANK )
free ( cgusb - > prod_string ) ;
if ( cgusb - > descriptor )
free ( cgusb - > descriptor ) ;
free ( cgusb - > found ) ;
@ -1387,7 +1432,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
@@ -1387,7 +1432,7 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
return NULL ;
}
void usb_uninit ( struct cgpu_info * cgpu )
static void _ usb_uninit( struct cgpu_info * cgpu )
{
applog ( LOG_DEBUG , " USB uninit %s%i " ,
cgpu - > drv - > name , cgpu - > device_id ) ;
@ -1396,14 +1441,28 @@ void usb_uninit(struct cgpu_info *cgpu)
@@ -1396,14 +1441,28 @@ void usb_uninit(struct cgpu_info *cgpu)
// if release_cgpu() was called due to a USB NODEV(err)
if ( ! cgpu - > usbdev )
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 ) ;
libusb_close ( cgpu - > usbdev - > handle ) ;
cgpu - > usbdev - > handle = NULL ;
cg_wunlock ( & cgusb_fd_lock ) ;
}
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
* DEVLOCK ( cgpu , pstate ) ;
@ -1412,7 +1471,7 @@ static void release_cgpu(struct cgpu_info *cgpu)
@@ -1412,7 +1471,7 @@ static void release_cgpu(struct cgpu_info *cgpu)
{
struct cg_usb_device * cgusb = cgpu - > usbdev ;
struct cgpu_info * lookcgpu ;
int i ;
int which_intinfo , i ;
applog ( LOG_DEBUG , " USB release %s%i " ,
cgpu - > drv - > name , cgpu - > device_id ) ;
@ -1445,16 +1504,24 @@ static void release_cgpu(struct cgpu_info *cgpu)
@@ -1445,16 +1504,24 @@ static void release_cgpu(struct cgpu_info *cgpu)
}
}
usb_uninit ( cgpu ) ;
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 * copy = calloc ( 1 , sizeof ( * copy ) ) ;
struct cgpu_info * copy ;
int pstate ;
DEVLOCK ( orig , pstate ) ;
copy = calloc ( 1 , sizeof ( * copy ) ) ;
if ( unlikely ( ! copy ) )
quit ( 1 , " Failed to calloc cgpu for %s in usb_copy_cgpu " , orig - > drv - > dname ) ;
@ -1471,6 +1538,75 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
@@ -1471,6 +1538,75 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
copy - > usbinfo . devlock = orig - > usbinfo . devlock ;
DEVUNLOCK ( orig , pstate ) ;
return copy ;
}
/*
* Used by CMR - use a different usbdev - since they must use a different
* USB handle due to using different interfaces ( libusb requirement )
* 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 ;
}
@ -1515,23 +1651,6 @@ struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devloc
@@ -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_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 )
{
struct cg_usb_device * cgusb = NULL ;
@ -1541,7 +1660,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1541,7 +1660,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
unsigned char strbuf [ STRBUFLEN + 1 ] ;
char devpath [ 32 ] ;
char devstr [ STRBUFLEN + 1 ] ;
int err , i , j , k , pstate ;
int err , ifinfo , epinfo , alt , epnum , pstate ;
int bad = USB_INIT_FAIL ;
int cfg ;
@ -1550,9 +1669,16 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -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 . device_address = libusb_get_device_address ( dev ) ;
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 ) ;
@ -1609,17 +1735,17 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1609,17 +1735,17 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
}
# 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 ) ;
err = libusb_detach_kernel_driver ( cgusb - > handle , found - > kernel ) ;
err = libusb_detach_kernel_driver ( cgusb - > handle , FOUNDIF ( found ) ) ;
if ( err = = 0 ) {
applog ( LOG_DEBUG ,
" USB init, kernel detached successfully %s " ,
devstr ) ;
" USB init, kernel detached interface %d successfully %s " ,
FOUNDIF ( found ) , devstr ) ;
} else {
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 ;
}
}
@ -1697,25 +1823,35 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1697,25 +1823,35 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
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 ;
}
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 ;
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 ;
}
@ -1723,29 +1859,30 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1723,29 +1859,30 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
}
}
}
}
for ( i = 0 ; i < found - > epcount ; i + + ) {
if ( found - > eps [ i ] . found = = false ) {
applog ( LOG_DEBUG , " USB init found == false %s " ,
devstr ) ;
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 ) {
switch ( err ) {
case LIBUSB_ERROR_BUSY :
applog ( LOG_WARNING ,
" USB init, claim interface %d in use %s " ,
found - > interface , devstr ) ;
FOUNDIF ( found ) , devstr ) ;
break ;
default :
applog ( LOG_DEBUG ,
" USB init, claim interface %d failed, err %d %s " ,
found - > interface , err , devstr ) ;
FOUNDIF ( found ) , err , devstr ) ;
}
goto c ldame;
goto re ldame;
}
cfg = - 1 ;
@ -1812,12 +1949,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
@@ -1812,12 +1949,13 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
reldame :
libusb_release_interface ( cgusb - > handle , found - > interface ) ;
libusb_release_interface ( cgusb - > handle , FOUNDIF ( found ) ) ;
cldame :
cg_wlock ( & cgusb_fd_lock ) ;
libusb_close ( cgusb - > handle ) ;
cgusb - > handle = NULL ;
cg_wunlock ( & cgusb_fd_lock ) ;
dame :
@ -1833,6 +1971,144 @@ out_unlock:
@@ -1833,6 +1971,144 @@ out_unlock:
return bad ;
}
// To get the extra interfaces on a multi interface device
struct cgpu_info * usb_init_intinfo ( struct cgpu_info * orig , int intinfo )
{
struct usb_find_devices * found ;
struct libusb_device * dev ;
struct cgpu_info * copy = NULL ;
char msgstr [ STRBUFLEN + 1 ] ;
char devstr [ STRBUFLEN + 1 ] ;
char devpath [ 32 ] ;
int err , pstate ;
DEVLOCK ( orig , pstate ) ;
snprintf ( msgstr , sizeof ( msgstr ) , " USB %s init_intinfo (%d:%d-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 )
{
struct usb_find_devices * found_use = NULL ;
@ -2391,7 +2667,7 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle,
@@ -2391,7 +2667,7 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle,
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 ;
bool ftdi ;
@ -2419,7 +2695,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
@@ -2419,7 +2695,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
usbdev = cgpu - > usbdev ;
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 )
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
@@ -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 ,
usbdev - > found - > eps [ ep ] . ep ,
USBEP ( usbdev , epinfo ) ,
ptr , usbbufread , & got , timeout ,
cgpu , MODE_BULK_READ , cmd , first ? SEQ0 : SEQ1 ) ;
cgtime ( & tv_finish ) ;
@ -2516,7 +2792,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
@@ -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
if ( usbdev - > buffer & & tot > ( int ) bufsiz ) {
usbdev - > bufamt = tot - bufsiz ;
memcpy ( usbdev - > buffer , ptr + bufsiz , usbdev - > bufamt ) ;
memcpy ( usbdev - > buffer , usbbuf + bufsiz , usbdev - > bufamt ) ;
tot - = usbdev - > bufamt ;
usbbuf [ tot ] = ' \0 ' ;
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
@@ -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 ,
usbdev - > found - > eps [ ep ] . ep , ptr ,
USBEP ( usbdev , epinfo ) , ptr ,
usbbufread , & got , timeout ,
cgpu , MODE_BULK_READ , cmd , first ? SEQ0 : SEQ1 ) ;
cgtime ( & tv_finish ) ;
@ -2664,7 +2940,7 @@ out_unlock:
@@ -2664,7 +2940,7 @@ out_unlock:
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 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
@@ -2675,7 +2951,7 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
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 ;
@ -2718,7 +2994,7 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
@@ -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 ;
}
err = usb_bulk_transfer ( usbdev - > handle ,
usbdev - > found - > eps [ ep ] . ep ,
USBEP ( usbdev , epinfo ) ,
( unsigned char * ) buf , bufsiz , & sent ,
timeout , cgpu , MODE_BULK_WRITE , cmd , first ? SEQ0 : SEQ1 ) ;
cgtime ( & tv_finish ) ;
@ -2956,7 +3232,7 @@ int usb_ftdi_set_latency(struct cgpu_info *cgpu)
@@ -2956,7 +3232,7 @@ int usb_ftdi_set_latency(struct cgpu_info *cgpu)
if ( ! err )
err = __usb_transfer ( cgpu , FTDI_TYPE_OUT , FTDI_REQUEST_LATENCY ,
cgpu - > usbdev - > found - > latency ,
cgpu - > usbdev - > found - > interface ,
USBIF ( cgpu - > usbdev ) ,
NULL , 0 , DEVTIMEOUT , C_LATENCY ) ;
}
@ -3083,7 +3359,7 @@ int usb_interface(struct cgpu_info *cgpu)
@@ -3083,7 +3359,7 @@ int usb_interface(struct cgpu_info *cgpu)
DEVLOCK ( cgpu , pstate ) ;
if ( cgpu - > usbdev )
interface = cgpu - > usbdev - > found - > interface ;
interface = USBIF ( cgpu - > usbdev ) ;
DEVUNLOCK ( cgpu , pstate ) ;