mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-11 07:17:58 +00:00
Merge branch 'master' into hashfast
This commit is contained in:
commit
118f9038a0
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Compile:
|
/* Compile:
|
||||||
* gcc api-example.c -I compat/jansson -o cgminer-api
|
* gcc api-example.c -Icompat/jansson -Icompat/libusb-1.0/libusb -o cgminer-api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -32,7 +32,6 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
#define SOCKETTYPE int
|
|
||||||
#define SOCKETFAIL(a) ((a) < 0)
|
#define SOCKETFAIL(a) ((a) < 0)
|
||||||
#define INVSOCK -1
|
#define INVSOCK -1
|
||||||
#define CLOSESOCKET close
|
#define CLOSESOCKET close
|
||||||
@ -140,8 +139,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RECVSIZE 65500
|
|
||||||
|
|
||||||
static const char SEPARATOR = '|';
|
static const char SEPARATOR = '|';
|
||||||
static const char COMMA = ',';
|
static const char COMMA = ',';
|
||||||
static const char EQ = '=';
|
static const char EQ = '=';
|
||||||
|
1
api.c
1
api.c
@ -22,6 +22,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
414
cgminer.c
414
cgminer.c
@ -27,6 +27,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#ifdef USE_USBUTILS
|
#ifdef USE_USBUTILS
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
@ -42,7 +43,11 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ccan/opt/opt.h>
|
#include <ccan/opt/opt.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#else
|
||||||
|
char *curly = ":D";
|
||||||
|
#endif
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <sha2.h>
|
#include <sha2.h>
|
||||||
|
|
||||||
@ -1632,6 +1637,7 @@ static struct opt_table opt_cmdline_table[] = {
|
|||||||
OPT_ENDTABLE
|
OPT_ENDTABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
static bool jobj_binary(const json_t *obj, const char *key,
|
static bool jobj_binary(const json_t *obj, const char *key,
|
||||||
void *buf, size_t buflen, bool required)
|
void *buf, size_t buflen, bool required)
|
||||||
{
|
{
|
||||||
@ -1654,6 +1660,7 @@ static bool jobj_binary(const json_t *obj, const char *key,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void calc_midstate(struct work *work)
|
static void calc_midstate(struct work *work)
|
||||||
{
|
{
|
||||||
@ -1702,7 +1709,10 @@ void free_work(struct work *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void gen_hash(unsigned char *data, unsigned char *hash, int len);
|
static void gen_hash(unsigned char *data, unsigned char *hash, int len);
|
||||||
|
static void calc_diff(struct work *work, int known);
|
||||||
|
char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000";
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
/* Process transactions with GBT by storing the binary value of the first
|
/* Process transactions with GBT by storing the binary value of the first
|
||||||
* transaction, and the hashes of the remaining transactions since these
|
* transaction, and the hashes of the remaining transactions since these
|
||||||
* remain constant with an altered coinbase when generating work. Must be
|
* remain constant with an altered coinbase when generating work. Must be
|
||||||
@ -1783,7 +1793,6 @@ static unsigned char *__gbt_merkleroot(struct pool *pool)
|
|||||||
return merkle_hash;
|
return merkle_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_diff(struct work *work, int known);
|
|
||||||
static bool work_decode(struct pool *pool, struct work *work, json_t *val);
|
static bool work_decode(struct pool *pool, struct work *work, json_t *val);
|
||||||
|
|
||||||
static void update_gbt(struct pool *pool)
|
static void update_gbt(struct pool *pool)
|
||||||
@ -1822,8 +1831,6 @@ static void update_gbt(struct pool *pool)
|
|||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000";
|
|
||||||
|
|
||||||
static void gen_gbt_work(struct pool *pool, struct work *work)
|
static void gen_gbt_work(struct pool *pool, struct work *work)
|
||||||
{
|
{
|
||||||
unsigned char *merkleroot;
|
unsigned char *merkleroot;
|
||||||
@ -2030,6 +2037,13 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
|
|||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#else /* HAVE_LIBCURL */
|
||||||
|
/* Always true with stratum */
|
||||||
|
#define pool_localgen(pool) (true)
|
||||||
|
#define json_rpc_call(curl, url, userpass, rpc_req, probe, longpoll, rolltime, pool, share) (NULL)
|
||||||
|
#define work_decode(pool, work, val) (false)
|
||||||
|
#define gen_gbt_work(pool, work) {}
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
int dev_from_id(int thr_id)
|
int dev_from_id(int thr_id)
|
||||||
{
|
{
|
||||||
@ -2197,18 +2211,6 @@ static void get_statline(char *buf, size_t bufsiz, struct cgpu_info *cgpu)
|
|||||||
cgpu->drv->get_statline(buf, bufsiz, cgpu);
|
cgpu->drv->get_statline(buf, bufsiz, cgpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_print_status(int thr_id)
|
|
||||||
{
|
|
||||||
struct cgpu_info *cgpu;
|
|
||||||
char logline[256];
|
|
||||||
|
|
||||||
cgpu = get_thr_cgpu(thr_id);
|
|
||||||
if (cgpu) {
|
|
||||||
get_statline(logline, sizeof(logline), cgpu);
|
|
||||||
printf("%s\n", logline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_CURSES
|
#ifdef HAVE_CURSES
|
||||||
#define CURBUFSIZ 256
|
#define CURBUFSIZ 256
|
||||||
#define cg_mvwprintw(win, y, x, fmt, ...) do { \
|
#define cg_mvwprintw(win, y, x, fmt, ...) do { \
|
||||||
@ -2348,12 +2350,6 @@ static void curses_print_devstatus(struct cgpu_info *cgpu, int count)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void print_status(int thr_id)
|
|
||||||
{
|
|
||||||
if (!curses_active)
|
|
||||||
text_print_status(thr_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_CURSES
|
#ifdef HAVE_CURSES
|
||||||
/* Check for window resize. Called with curses mutex locked */
|
/* Check for window resize. Called with curses mutex locked */
|
||||||
static inline void change_logwinsize(void)
|
static inline void change_logwinsize(void)
|
||||||
@ -2645,6 +2641,25 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
static void text_print_status(int thr_id)
|
||||||
|
{
|
||||||
|
struct cgpu_info *cgpu;
|
||||||
|
char logline[256];
|
||||||
|
|
||||||
|
cgpu = get_thr_cgpu(thr_id);
|
||||||
|
if (cgpu) {
|
||||||
|
get_statline(logline, sizeof(logline), cgpu);
|
||||||
|
printf("%s\n", logline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_status(int thr_id)
|
||||||
|
{
|
||||||
|
if (!curses_active)
|
||||||
|
text_print_status(thr_id);
|
||||||
|
}
|
||||||
|
|
||||||
static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
|
static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
|
||||||
{
|
{
|
||||||
char *hexstr = NULL;
|
char *hexstr = NULL;
|
||||||
@ -2829,6 +2844,62 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_upstream_work(struct work *work, CURL *curl)
|
||||||
|
{
|
||||||
|
struct pool *pool = work->pool;
|
||||||
|
struct cgminer_pool_stats *pool_stats = &(pool->cgminer_pool_stats);
|
||||||
|
struct timeval tv_elapsed;
|
||||||
|
json_t *val = NULL;
|
||||||
|
bool rc = false;
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
applog(LOG_DEBUG, "DBG: sending %s get RPC call: %s", pool->rpc_url, pool->rpc_req);
|
||||||
|
|
||||||
|
url = pool->rpc_url;
|
||||||
|
|
||||||
|
cgtime(&work->tv_getwork);
|
||||||
|
|
||||||
|
val = json_rpc_call(curl, url, pool->rpc_userpass, pool->rpc_req, false,
|
||||||
|
false, &work->rolltime, pool, false);
|
||||||
|
pool_stats->getwork_attempts++;
|
||||||
|
|
||||||
|
if (likely(val)) {
|
||||||
|
rc = work_decode(pool, work, val);
|
||||||
|
if (unlikely(!rc))
|
||||||
|
applog(LOG_DEBUG, "Failed to decode work in get_upstream_work");
|
||||||
|
} else
|
||||||
|
applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work");
|
||||||
|
|
||||||
|
cgtime(&work->tv_getwork_reply);
|
||||||
|
timersub(&(work->tv_getwork_reply), &(work->tv_getwork), &tv_elapsed);
|
||||||
|
pool_stats->getwork_wait_rolling += ((double)tv_elapsed.tv_sec + ((double)tv_elapsed.tv_usec / 1000000)) * 0.63;
|
||||||
|
pool_stats->getwork_wait_rolling /= 1.63;
|
||||||
|
|
||||||
|
timeradd(&tv_elapsed, &(pool_stats->getwork_wait), &(pool_stats->getwork_wait));
|
||||||
|
if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_max), >)) {
|
||||||
|
pool_stats->getwork_wait_max.tv_sec = tv_elapsed.tv_sec;
|
||||||
|
pool_stats->getwork_wait_max.tv_usec = tv_elapsed.tv_usec;
|
||||||
|
}
|
||||||
|
if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_min), <)) {
|
||||||
|
pool_stats->getwork_wait_min.tv_sec = tv_elapsed.tv_sec;
|
||||||
|
pool_stats->getwork_wait_min.tv_usec = tv_elapsed.tv_usec;
|
||||||
|
}
|
||||||
|
pool_stats->getwork_calls++;
|
||||||
|
|
||||||
|
work->pool = pool;
|
||||||
|
work->longpoll = false;
|
||||||
|
work->getwork_mode = GETWORK_MODE_POOL;
|
||||||
|
calc_diff(work, 0);
|
||||||
|
total_getworks++;
|
||||||
|
pool->getwork_requested++;
|
||||||
|
|
||||||
|
if (likely(val))
|
||||||
|
json_decref(val);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
/* Specifies whether we can use this pool for work or not. */
|
/* Specifies whether we can use this pool for work or not. */
|
||||||
static bool pool_unworkable(struct pool *pool)
|
static bool pool_unworkable(struct pool *pool)
|
||||||
{
|
{
|
||||||
@ -3017,61 +3088,6 @@ static void get_benchmark_work(struct work *work)
|
|||||||
calc_diff(work, 0);
|
calc_diff(work, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_upstream_work(struct work *work, CURL *curl)
|
|
||||||
{
|
|
||||||
struct pool *pool = work->pool;
|
|
||||||
struct cgminer_pool_stats *pool_stats = &(pool->cgminer_pool_stats);
|
|
||||||
struct timeval tv_elapsed;
|
|
||||||
json_t *val = NULL;
|
|
||||||
bool rc = false;
|
|
||||||
char *url;
|
|
||||||
|
|
||||||
applog(LOG_DEBUG, "DBG: sending %s get RPC call: %s", pool->rpc_url, pool->rpc_req);
|
|
||||||
|
|
||||||
url = pool->rpc_url;
|
|
||||||
|
|
||||||
cgtime(&work->tv_getwork);
|
|
||||||
|
|
||||||
val = json_rpc_call(curl, url, pool->rpc_userpass, pool->rpc_req, false,
|
|
||||||
false, &work->rolltime, pool, false);
|
|
||||||
pool_stats->getwork_attempts++;
|
|
||||||
|
|
||||||
if (likely(val)) {
|
|
||||||
rc = work_decode(pool, work, val);
|
|
||||||
if (unlikely(!rc))
|
|
||||||
applog(LOG_DEBUG, "Failed to decode work in get_upstream_work");
|
|
||||||
} else
|
|
||||||
applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work");
|
|
||||||
|
|
||||||
cgtime(&work->tv_getwork_reply);
|
|
||||||
timersub(&(work->tv_getwork_reply), &(work->tv_getwork), &tv_elapsed);
|
|
||||||
pool_stats->getwork_wait_rolling += ((double)tv_elapsed.tv_sec + ((double)tv_elapsed.tv_usec / 1000000)) * 0.63;
|
|
||||||
pool_stats->getwork_wait_rolling /= 1.63;
|
|
||||||
|
|
||||||
timeradd(&tv_elapsed, &(pool_stats->getwork_wait), &(pool_stats->getwork_wait));
|
|
||||||
if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_max), >)) {
|
|
||||||
pool_stats->getwork_wait_max.tv_sec = tv_elapsed.tv_sec;
|
|
||||||
pool_stats->getwork_wait_max.tv_usec = tv_elapsed.tv_usec;
|
|
||||||
}
|
|
||||||
if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_min), <)) {
|
|
||||||
pool_stats->getwork_wait_min.tv_sec = tv_elapsed.tv_sec;
|
|
||||||
pool_stats->getwork_wait_min.tv_usec = tv_elapsed.tv_usec;
|
|
||||||
}
|
|
||||||
pool_stats->getwork_calls++;
|
|
||||||
|
|
||||||
work->pool = pool;
|
|
||||||
work->longpoll = false;
|
|
||||||
work->getwork_mode = GETWORK_MODE_POOL;
|
|
||||||
calc_diff(work, 0);
|
|
||||||
total_getworks++;
|
|
||||||
pool->getwork_requested++;
|
|
||||||
|
|
||||||
if (likely(val))
|
|
||||||
json_decref(val);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_CURSES
|
#ifdef HAVE_CURSES
|
||||||
static void disable_curses_windows(void)
|
static void disable_curses_windows(void)
|
||||||
{
|
{
|
||||||
@ -3239,6 +3255,7 @@ static void sighandler(int __maybe_unused sig)
|
|||||||
kill_work();
|
kill_work();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
/* Called with pool_lock held. Recruit an extra curl if none are available for
|
/* Called with pool_lock held. Recruit an extra curl if none are available for
|
||||||
* this pool. */
|
* this pool. */
|
||||||
static void recruit_curl(struct pool *pool)
|
static void recruit_curl(struct pool *pool)
|
||||||
@ -3320,7 +3337,7 @@ static inline bool should_roll(struct work *work)
|
|||||||
cgtime(&now);
|
cgtime(&now);
|
||||||
if (now.tv_sec - work->tv_staged.tv_sec > expiry)
|
if (now.tv_sec - work->tv_staged.tv_sec > expiry)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3351,36 +3368,47 @@ static void roll_work(struct work *work)
|
|||||||
work->id = total_work++;
|
work->id = total_work++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Duplicates any dynamically allocated arrays within the work struct to
|
static void *submit_work_thread(void *userdata)
|
||||||
* prevent a copied work struct from freeing ram belonging to another struct */
|
|
||||||
void __copy_work(struct work *work, struct work *base_work)
|
|
||||||
{
|
{
|
||||||
int id = work->id;
|
struct work *work = (struct work *)userdata;
|
||||||
|
struct pool *pool = work->pool;
|
||||||
|
bool resubmit = false;
|
||||||
|
struct curl_ent *ce;
|
||||||
|
|
||||||
clean_work(work);
|
pthread_detach(pthread_self());
|
||||||
memcpy(work, base_work, sizeof(struct work));
|
|
||||||
/* Keep the unique new id assigned during make_work to prevent copied
|
|
||||||
* work from having the same id. */
|
|
||||||
work->id = id;
|
|
||||||
if (base_work->job_id)
|
|
||||||
work->job_id = strdup(base_work->job_id);
|
|
||||||
if (base_work->nonce1)
|
|
||||||
work->nonce1 = strdup(base_work->nonce1);
|
|
||||||
if (base_work->ntime)
|
|
||||||
work->ntime = strdup(base_work->ntime);
|
|
||||||
if (base_work->coinbase)
|
|
||||||
work->coinbase = strdup(base_work->coinbase);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generates a copy of an existing work struct, creating fresh heap allocations
|
RenameThread("submit_work");
|
||||||
* for all dynamically allocated arrays within the struct */
|
|
||||||
struct work *copy_work(struct work *base_work)
|
|
||||||
{
|
|
||||||
struct work *work = make_work();
|
|
||||||
|
|
||||||
__copy_work(work, base_work);
|
applog(LOG_DEBUG, "Creating extra submit work thread");
|
||||||
|
|
||||||
return work;
|
ce = pop_curl_entry(pool);
|
||||||
|
/* submit solution to bitcoin via JSON-RPC */
|
||||||
|
while (!submit_upstream_work(work, ce->curl, resubmit)) {
|
||||||
|
if (opt_lowmem) {
|
||||||
|
applog(LOG_NOTICE, "Pool %d share being discarded to minimise memory cache", pool->pool_no);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resubmit = true;
|
||||||
|
if (stale_work(work, true)) {
|
||||||
|
applog(LOG_NOTICE, "Pool %d share became stale while retrying submit, discarding", pool->pool_no);
|
||||||
|
|
||||||
|
mutex_lock(&stats_lock);
|
||||||
|
total_stale++;
|
||||||
|
pool->stale_shares++;
|
||||||
|
total_diff_stale += work->work_difficulty;
|
||||||
|
pool->diff_stale += work->work_difficulty;
|
||||||
|
mutex_unlock(&stats_lock);
|
||||||
|
|
||||||
|
free_work(work);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pause, then restart work-request loop */
|
||||||
|
applog(LOG_INFO, "json_rpc_call failed on submit_work, retrying");
|
||||||
|
}
|
||||||
|
push_curl_entry(ce, pool);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct work *make_clone(struct work *work)
|
static struct work *make_clone(struct work *work)
|
||||||
@ -3429,6 +3457,81 @@ out_unlock:
|
|||||||
return cloned;
|
return cloned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clones work by rolling it if possible, and returning a clone instead of the
|
||||||
|
* original work item which gets staged again to possibly be rolled again in
|
||||||
|
* the future */
|
||||||
|
static struct work *clone_work(struct work *work)
|
||||||
|
{
|
||||||
|
int mrs = mining_threads + opt_queue - total_staged();
|
||||||
|
struct work *work_clone;
|
||||||
|
bool cloned;
|
||||||
|
|
||||||
|
if (mrs < 1)
|
||||||
|
return work;
|
||||||
|
|
||||||
|
cloned = false;
|
||||||
|
work_clone = make_clone(work);
|
||||||
|
while (mrs-- > 0 && can_roll(work) && should_roll(work)) {
|
||||||
|
applog(LOG_DEBUG, "Pushing rolled converted work to stage thread");
|
||||||
|
stage_work(work_clone);
|
||||||
|
roll_work(work);
|
||||||
|
work_clone = make_clone(work);
|
||||||
|
/* Roll it again to prevent duplicates should this be used
|
||||||
|
* directly later on */
|
||||||
|
roll_work(work);
|
||||||
|
cloned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cloned) {
|
||||||
|
stage_work(work);
|
||||||
|
return work_clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_work(work_clone);
|
||||||
|
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_LIBCURL */
|
||||||
|
static void *submit_work_thread(void __maybe_unused *userdata)
|
||||||
|
{
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
|
/* Duplicates any dynamically allocated arrays within the work struct to
|
||||||
|
* prevent a copied work struct from freeing ram belonging to another struct */
|
||||||
|
void __copy_work(struct work *work, struct work *base_work)
|
||||||
|
{
|
||||||
|
int id = work->id;
|
||||||
|
|
||||||
|
clean_work(work);
|
||||||
|
memcpy(work, base_work, sizeof(struct work));
|
||||||
|
/* Keep the unique new id assigned during make_work to prevent copied
|
||||||
|
* work from having the same id. */
|
||||||
|
work->id = id;
|
||||||
|
if (base_work->job_id)
|
||||||
|
work->job_id = strdup(base_work->job_id);
|
||||||
|
if (base_work->nonce1)
|
||||||
|
work->nonce1 = strdup(base_work->nonce1);
|
||||||
|
if (base_work->ntime)
|
||||||
|
work->ntime = strdup(base_work->ntime);
|
||||||
|
if (base_work->coinbase)
|
||||||
|
work->coinbase = strdup(base_work->coinbase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generates a copy of an existing work struct, creating fresh heap allocations
|
||||||
|
* for all dynamically allocated arrays within the struct */
|
||||||
|
struct work *copy_work(struct work *base_work)
|
||||||
|
{
|
||||||
|
struct work *work = make_work();
|
||||||
|
|
||||||
|
__copy_work(work, base_work);
|
||||||
|
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
|
||||||
static void pool_died(struct pool *pool)
|
static void pool_died(struct pool *pool)
|
||||||
{
|
{
|
||||||
if (!pool_tset(pool, &pool->idle)) {
|
if (!pool_tset(pool, &pool->idle)) {
|
||||||
@ -3572,49 +3675,6 @@ static void rebuild_hash(struct work *work)
|
|||||||
|
|
||||||
static bool cnx_needed(struct pool *pool);
|
static bool cnx_needed(struct pool *pool);
|
||||||
|
|
||||||
static void *submit_work_thread(void *userdata)
|
|
||||||
{
|
|
||||||
struct work *work = (struct work *)userdata;
|
|
||||||
struct pool *pool = work->pool;
|
|
||||||
bool resubmit = false;
|
|
||||||
struct curl_ent *ce;
|
|
||||||
|
|
||||||
pthread_detach(pthread_self());
|
|
||||||
|
|
||||||
RenameThread("submit_work");
|
|
||||||
|
|
||||||
applog(LOG_DEBUG, "Creating extra submit work thread");
|
|
||||||
|
|
||||||
ce = pop_curl_entry(pool);
|
|
||||||
/* submit solution to bitcoin via JSON-RPC */
|
|
||||||
while (!submit_upstream_work(work, ce->curl, resubmit)) {
|
|
||||||
if (opt_lowmem) {
|
|
||||||
applog(LOG_NOTICE, "Pool %d share being discarded to minimise memory cache", pool->pool_no);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
resubmit = true;
|
|
||||||
if (stale_work(work, true)) {
|
|
||||||
applog(LOG_NOTICE, "Pool %d share became stale while retrying submit, discarding", pool->pool_no);
|
|
||||||
|
|
||||||
mutex_lock(&stats_lock);
|
|
||||||
total_stale++;
|
|
||||||
pool->stale_shares++;
|
|
||||||
total_diff_stale += work->work_difficulty;
|
|
||||||
pool->diff_stale += work->work_difficulty;
|
|
||||||
mutex_unlock(&stats_lock);
|
|
||||||
|
|
||||||
free_work(work);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pause, then restart work-request loop */
|
|
||||||
applog(LOG_INFO, "json_rpc_call failed on submit_work, retrying");
|
|
||||||
}
|
|
||||||
push_curl_entry(ce, pool);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the pool that currently has the highest priority */
|
/* Find the pool that currently has the highest priority */
|
||||||
static struct pool *priority_pool(int choice)
|
static struct pool *priority_pool(int choice)
|
||||||
{
|
{
|
||||||
@ -5761,41 +5821,6 @@ static struct work *hash_pop(void)
|
|||||||
return work;
|
return work;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clones work by rolling it if possible, and returning a clone instead of the
|
|
||||||
* original work item which gets staged again to possibly be rolled again in
|
|
||||||
* the future */
|
|
||||||
static struct work *clone_work(struct work *work)
|
|
||||||
{
|
|
||||||
int mrs = mining_threads + opt_queue - total_staged();
|
|
||||||
struct work *work_clone;
|
|
||||||
bool cloned;
|
|
||||||
|
|
||||||
if (mrs < 1)
|
|
||||||
return work;
|
|
||||||
|
|
||||||
cloned = false;
|
|
||||||
work_clone = make_clone(work);
|
|
||||||
while (mrs-- > 0 && can_roll(work) && should_roll(work)) {
|
|
||||||
applog(LOG_DEBUG, "Pushing rolled converted work to stage thread");
|
|
||||||
stage_work(work_clone);
|
|
||||||
roll_work(work);
|
|
||||||
work_clone = make_clone(work);
|
|
||||||
/* Roll it again to prevent duplicates should this be used
|
|
||||||
* directly later on */
|
|
||||||
roll_work(work);
|
|
||||||
cloned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cloned) {
|
|
||||||
stage_work(work);
|
|
||||||
return work_clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_work(work_clone);
|
|
||||||
|
|
||||||
return work;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gen_hash(unsigned char *data, unsigned char *hash, int len)
|
static void gen_hash(unsigned char *data, unsigned char *hash, int len)
|
||||||
{
|
{
|
||||||
unsigned char hash1[32];
|
unsigned char hash1[32];
|
||||||
@ -6468,6 +6493,7 @@ enum {
|
|||||||
FAILURE_INTERVAL = 30,
|
FAILURE_INTERVAL = 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
/* Stage another work item from the work returned in a longpoll */
|
/* Stage another work item from the work returned in a longpoll */
|
||||||
static void convert_to_work(json_t *val, int rolltime, struct pool *pool, struct timeval *tv_lp, struct timeval *tv_lp_reply)
|
static void convert_to_work(json_t *val, int rolltime, struct pool *pool, struct timeval *tv_lp, struct timeval *tv_lp_reply)
|
||||||
{
|
{
|
||||||
@ -6538,6 +6564,7 @@ static struct pool *select_longpoll_pool(struct pool *cp)
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
/* This will make the longpoll thread wait till it's the current pool, or it
|
/* This will make the longpoll thread wait till it's the current pool, or it
|
||||||
* has been flagged as rejecting, before attempting to open any connections.
|
* has been flagged as rejecting, before attempting to open any connections.
|
||||||
@ -6553,6 +6580,7 @@ static void wait_lpcurrent(struct pool *pool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
static void *longpoll_thread(void *userdata)
|
static void *longpoll_thread(void *userdata)
|
||||||
{
|
{
|
||||||
struct pool *cp = (struct pool *)userdata;
|
struct pool *cp = (struct pool *)userdata;
|
||||||
@ -6680,6 +6708,13 @@ out:
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#else /* HAVE_LIBCURL */
|
||||||
|
static void *longpoll_thread(void __maybe_unused *userdata)
|
||||||
|
{
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
void reinit_device(struct cgpu_info *cgpu)
|
void reinit_device(struct cgpu_info *cgpu)
|
||||||
{
|
{
|
||||||
@ -8160,7 +8195,6 @@ begin_bench:
|
|||||||
int ts, max_staged = opt_queue;
|
int ts, max_staged = opt_queue;
|
||||||
struct pool *pool, *cp;
|
struct pool *pool, *cp;
|
||||||
bool lagging = false;
|
bool lagging = false;
|
||||||
struct curl_ent *ce;
|
|
||||||
struct work *work;
|
struct work *work;
|
||||||
|
|
||||||
cp = current_pool();
|
cp = current_pool();
|
||||||
@ -8211,6 +8245,16 @@ retry:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt_benchmark) {
|
||||||
|
get_benchmark_work(work);
|
||||||
|
applog(LOG_DEBUG, "Generated benchmark work");
|
||||||
|
stage_work(work);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
struct curl_ent *ce;
|
||||||
|
|
||||||
if (pool->has_gbt) {
|
if (pool->has_gbt) {
|
||||||
while (pool->idle) {
|
while (pool->idle) {
|
||||||
struct pool *altpool = select_pool(true);
|
struct pool *altpool = select_pool(true);
|
||||||
@ -8233,13 +8277,6 @@ retry:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_benchmark) {
|
|
||||||
get_benchmark_work(work);
|
|
||||||
applog(LOG_DEBUG, "Generated benchmark work");
|
|
||||||
stage_work(work);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
work->pool = pool;
|
work->pool = pool;
|
||||||
ce = pop_curl_entry(pool);
|
ce = pop_curl_entry(pool);
|
||||||
/* obtain new work from bitcoin via JSON-RPC */
|
/* obtain new work from bitcoin via JSON-RPC */
|
||||||
@ -8262,6 +8299,7 @@ retry:
|
|||||||
applog(LOG_DEBUG, "Generated getwork work");
|
applog(LOG_DEBUG, "Generated getwork work");
|
||||||
stage_work(work);
|
stage_work(work);
|
||||||
push_curl_entry(ce, pool);
|
push_curl_entry(ce, pool);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
3
compat/.gitignore
vendored
Normal file
3
compat/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
libusb-1.0/libusb/libusb-1.0.la
|
||||||
|
libusb-1.0/libusb/*.lo
|
||||||
|
libusb-1.0/libusb/os/*.lo
|
28
configure.ac
28
configure.ac
@ -365,15 +365,26 @@ fi
|
|||||||
AC_SUBST(LIBUSB_LIBS)
|
AC_SUBST(LIBUSB_LIBS)
|
||||||
AC_SUBST(LIBUSB_CFLAGS)
|
AC_SUBST(LIBUSB_CFLAGS)
|
||||||
|
|
||||||
if test "x$have_win32" != xtrue; then
|
AC_ARG_ENABLE([libcurl],
|
||||||
PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.25.0], [AC_DEFINE([CURL_HAS_KEEPALIVE], [1], [Defined if version of curl supports keepalive.])],
|
[AC_HELP_STRING([--disable-libcurl],[Disable building with libcurl for getwork and GBT support])],
|
||||||
[PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.18.2], ,[AC_MSG_ERROR([Missing required libcurl dev >= 7.18.2])])])
|
[libcurl=$enableval]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x$libcurl" != xno; then
|
||||||
|
if test "x$have_win32" != xtrue; then
|
||||||
|
PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.25.0], [AC_DEFINE([CURL_HAS_KEEPALIVE], [1], [Defined if version of curl supports keepalive.])],
|
||||||
|
[PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.18.2], ,[AC_MSG_ERROR([Missing required libcurl dev >= 7.18.2])])])
|
||||||
|
else
|
||||||
|
PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.25.0], ,[AC_MSG_ERROR([Missing required libcurl dev >= 7.25.0])])
|
||||||
|
AC_DEFINE([CURL_HAS_KEEPALIVE], [1])
|
||||||
|
fi
|
||||||
|
AC_DEFINE([HAVE_LIBCURL], [1], [Defined to 1 if libcurl support built in])
|
||||||
else
|
else
|
||||||
PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.25.0], ,[AC_MSG_ERROR([Missing required libcurl dev >= 7.25.0])])
|
LIBCURL_LIBS=""
|
||||||
AC_DEFINE([CURL_HAS_KEEPALIVE], [1])
|
|
||||||
fi
|
fi
|
||||||
AC_SUBST(LIBCURL_LIBS)
|
AC_SUBST(LIBCURL_LIBS)
|
||||||
|
|
||||||
|
|
||||||
#check execv signature
|
#check execv signature
|
||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
@ -462,8 +473,15 @@ echo
|
|||||||
echo "Configuration Options Summary:"
|
echo "Configuration Options Summary:"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
if test "x$libcurl" != xno; then
|
||||||
|
echo " libcurl(GBT+getwork).: Enabled: $LIBCURL_LIBS"
|
||||||
|
else
|
||||||
|
echo " libcurl(GBT+getwork).: Disabled"
|
||||||
|
fi
|
||||||
|
|
||||||
echo " curses.TUI...........: $cursesmsg"
|
echo " curses.TUI...........: $cursesmsg"
|
||||||
|
|
||||||
|
|
||||||
if test "x$opencl" != xno; then
|
if test "x$opencl" != xno; then
|
||||||
if test $found_opencl = 1; then
|
if test $found_opencl = 1; then
|
||||||
echo " OpenCL...............: FOUND. GPU mining support enabled"
|
echo " OpenCL...............: FOUND. GPU mining support enabled"
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
@ -862,12 +872,47 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
|
|||||||
timersub(&tv_finish, &tv_start, &(info->golden_tv));
|
timersub(&tv_finish, &tv_start, &(info->golden_tv));
|
||||||
|
|
||||||
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));
|
||||||
|
16
miner.h
16
miner.h
@ -8,7 +8,17 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#else
|
||||||
|
typedef char CURL;
|
||||||
|
extern char *curly;
|
||||||
|
#define curl_easy_init(curl) (curly)
|
||||||
|
#define curl_easy_cleanup(curl) {}
|
||||||
|
#define curl_global_cleanup() {}
|
||||||
|
#define CURL_GLOBAL_ALL 0
|
||||||
|
#define curl_global_init(X) (0)
|
||||||
|
#endif
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
|
||||||
#include "elist.h"
|
#include "elist.h"
|
||||||
@ -913,10 +923,12 @@ extern int swork_id;
|
|||||||
extern pthread_rwlock_t netacc_lock;
|
extern pthread_rwlock_t netacc_lock;
|
||||||
|
|
||||||
extern const uint32_t sha256_init_state[];
|
extern const uint32_t sha256_init_state[];
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
||||||
const char *rpc_req, bool, bool, int *,
|
const char *rpc_req, bool, bool, int *,
|
||||||
struct pool *pool, bool);
|
struct pool *pool, bool);
|
||||||
extern const char *proxytype(curl_proxytype proxytype);
|
#endif
|
||||||
|
extern const char *proxytype(proxytypes_t proxytype);
|
||||||
extern char *get_proxy(char *url, struct pool *pool);
|
extern char *get_proxy(char *url, struct pool *pool);
|
||||||
extern char *bin2hex(const unsigned char *p, size_t len);
|
extern char *bin2hex(const unsigned char *p, size_t len);
|
||||||
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
||||||
@ -1156,7 +1168,7 @@ struct pool {
|
|||||||
char *rpc_url;
|
char *rpc_url;
|
||||||
char *rpc_userpass;
|
char *rpc_userpass;
|
||||||
char *rpc_user, *rpc_pass;
|
char *rpc_user, *rpc_pass;
|
||||||
curl_proxytype rpc_proxytype;
|
proxytypes_t rpc_proxytype;
|
||||||
char *rpc_proxy;
|
char *rpc_proxy;
|
||||||
|
|
||||||
pthread_mutex_t pool_lock;
|
pthread_mutex_t pool_lock;
|
||||||
|
1
ocl.c
1
ocl.c
@ -14,6 +14,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
566
usbutils.c
566
usbutils.c
@ -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[] = {
|
#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
|
||||||
@ -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),
|
INTINFO(bas_ints) },
|
||||||
.eps = bas_eps },
|
|
||||||
#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),
|
INTINFO(bfl_ints) },
|
||||||
.eps = bfl_eps },
|
|
||||||
#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),
|
INTINFO(mmq_ints) },
|
||||||
.eps = mmq_eps },
|
|
||||||
#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),
|
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_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),
|
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",
|
||||||
@ -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),
|
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,
|
||||||
@ -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),
|
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
|
||||||
@ -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,
|
.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
|
||||||
@ -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);
|
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);
|
||||||
|
|
||||||
@ -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",
|
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);
|
||||||
|
|
||||||
@ -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",
|
"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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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) {
|
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++) {
|
for (ifinfo = 0; ifinfo < found->intinfo_count; ifinfo++) {
|
||||||
idesc = &(config->interface[found->interface].altsetting[i]);
|
int interface = found->intinfos[ifinfo].interface;
|
||||||
for (j = 0; j < (int)(idesc->bNumEndpoints); j++) {
|
for (alt = 0; alt < config->interface[interface].num_altsetting; alt++) {
|
||||||
epdesc = &(idesc->endpoint[j]);
|
idesc = &(config->interface[interface].altsetting[alt]);
|
||||||
for (k = 0; k < found->epcount; k++) {
|
for (epnum = 0; epnum < (int)(idesc->bNumEndpoints); epnum++) {
|
||||||
if (!found->eps[k].found) {
|
struct usb_epinfo *epinfos = found->intinfos[ifinfo].epinfos;
|
||||||
if (epdesc->bmAttributes == found->eps[k].att
|
epdesc = &(idesc->endpoint[epnum]);
|
||||||
&& epdesc->wMaxPacketSize >= found->eps[k].size
|
for (epinfo = 0; epinfo < found->intinfos[ifinfo].epinfo_count; epinfo++) {
|
||||||
&& epdesc->bEndpointAddress == found->eps[k].ep) {
|
if (!epinfos[epinfo].found) {
|
||||||
found->eps[k].found = true;
|
if (epdesc->bmAttributes == epinfos[epinfo].att
|
||||||
found->wMaxPacketSize = epdesc->wMaxPacketSize;
|
&& epdesc->wMaxPacketSize >= epinfos[epinfo].size
|
||||||
break;
|
&& 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;
|
||||||
@ -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);
|
||||||
|
|
||||||
|
20
usbutils.h
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,
|
||||||
@ -149,14 +155,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
|
||||||
@ -343,6 +348,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);
|
||||||
|
153
util.c
153
util.c
@ -16,7 +16,9 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#endif
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -45,6 +47,44 @@
|
|||||||
#define DEFAULT_SOCKWAIT 60
|
#define DEFAULT_SOCKWAIT 60
|
||||||
|
|
||||||
bool successful_connect = false;
|
bool successful_connect = false;
|
||||||
|
static void keep_sockalive(SOCKETTYPE fd)
|
||||||
|
{
|
||||||
|
const int tcp_one = 1;
|
||||||
|
#ifndef WIN32
|
||||||
|
const int tcp_keepidle = 45;
|
||||||
|
const int tcp_keepintvl = 30;
|
||||||
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
|
||||||
|
fcntl(fd, F_SETFL, O_NONBLOCK | flags);
|
||||||
|
#else
|
||||||
|
u_long flags = 1;
|
||||||
|
|
||||||
|
ioctlsocket(fd, FIONBIO, &flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void *)&tcp_one, sizeof(tcp_one));
|
||||||
|
if (!opt_delaynet)
|
||||||
|
#ifndef __linux
|
||||||
|
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one));
|
||||||
|
#else /* __linux */
|
||||||
|
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one));
|
||||||
|
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_one, sizeof(tcp_one));
|
||||||
|
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle));
|
||||||
|
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl));
|
||||||
|
#endif /* __linux */
|
||||||
|
|
||||||
|
#ifdef __APPLE_CC__
|
||||||
|
setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl));
|
||||||
|
#endif /* __APPLE_CC__ */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tq_ent {
|
||||||
|
void *data;
|
||||||
|
struct list_head q_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
struct timeval nettime;
|
struct timeval nettime;
|
||||||
|
|
||||||
struct data_buffer {
|
struct data_buffer {
|
||||||
@ -67,11 +107,6 @@ struct header_info {
|
|||||||
bool hadexpire;
|
bool hadexpire;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tq_ent {
|
|
||||||
void *data;
|
|
||||||
struct list_head q_node;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void databuf_free(struct data_buffer *db)
|
static void databuf_free(struct data_buffer *db)
|
||||||
{
|
{
|
||||||
if (!db)
|
if (!db)
|
||||||
@ -202,36 +237,19 @@ out:
|
|||||||
return ptrlen;
|
return ptrlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keep_sockalive(SOCKETTYPE fd)
|
static void last_nettime(struct timeval *last)
|
||||||
{
|
{
|
||||||
const int tcp_one = 1;
|
rd_lock(&netacc_lock);
|
||||||
#ifndef WIN32
|
last->tv_sec = nettime.tv_sec;
|
||||||
const int tcp_keepidle = 45;
|
last->tv_usec = nettime.tv_usec;
|
||||||
const int tcp_keepintvl = 30;
|
rd_unlock(&netacc_lock);
|
||||||
int flags = fcntl(fd, F_GETFL, 0);
|
}
|
||||||
|
|
||||||
fcntl(fd, F_SETFL, O_NONBLOCK | flags);
|
|
||||||
#else
|
|
||||||
u_long flags = 1;
|
|
||||||
|
|
||||||
ioctlsocket(fd, FIONBIO, &flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void *)&tcp_one, sizeof(tcp_one));
|
|
||||||
if (!opt_delaynet)
|
|
||||||
#ifndef __linux
|
|
||||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one));
|
|
||||||
#else /* __linux */
|
|
||||||
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one));
|
|
||||||
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_one, sizeof(tcp_one));
|
|
||||||
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle));
|
|
||||||
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl));
|
|
||||||
#endif /* __linux */
|
|
||||||
|
|
||||||
#ifdef __APPLE_CC__
|
|
||||||
setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl));
|
|
||||||
#endif /* __APPLE_CC__ */
|
|
||||||
|
|
||||||
|
static void set_nettime(void)
|
||||||
|
{
|
||||||
|
wr_lock(&netacc_lock);
|
||||||
|
cgtime(&nettime);
|
||||||
|
wr_unlock(&netacc_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CURL_HAS_KEEPALIVE
|
#if CURL_HAS_KEEPALIVE
|
||||||
@ -255,21 +273,6 @@ static void keep_curlalive(CURL *curl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void last_nettime(struct timeval *last)
|
|
||||||
{
|
|
||||||
rd_lock(&netacc_lock);
|
|
||||||
last->tv_sec = nettime.tv_sec;
|
|
||||||
last->tv_usec = nettime.tv_usec;
|
|
||||||
rd_unlock(&netacc_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_nettime(void)
|
|
||||||
{
|
|
||||||
wr_lock(&netacc_lock);
|
|
||||||
cgtime(&nettime);
|
|
||||||
wr_unlock(&netacc_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type,
|
static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type,
|
||||||
__maybe_unused char *data, size_t size, void *userdata)
|
__maybe_unused char *data, size_t size, void *userdata)
|
||||||
{
|
{
|
||||||
@ -513,29 +516,35 @@ err_out:
|
|||||||
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
|
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#define PROXY_HTTP CURLPROXY_HTTP
|
||||||
|
#define PROXY_HTTP_1_0 CURLPROXY_HTTP_1_0
|
||||||
|
#define PROXY_SOCKS4 CURLPROXY_SOCKS4
|
||||||
|
#define PROXY_SOCKS5 CURLPROXY_SOCKS5
|
||||||
|
#define PROXY_SOCKS4A CURLPROXY_SOCKS4A
|
||||||
|
#define PROXY_SOCKS5H CURLPROXY_SOCKS5_HOSTNAME
|
||||||
|
#else /* HAVE_LIBCURL */
|
||||||
|
#define PROXY_HTTP 0
|
||||||
|
#define PROXY_HTTP_1_0 1
|
||||||
|
#define PROXY_SOCKS4 2
|
||||||
|
#define PROXY_SOCKS5 3
|
||||||
|
#define PROXY_SOCKS4A 4
|
||||||
|
#define PROXY_SOCKS5H 5
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7)
|
|
||||||
static struct {
|
static struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
curl_proxytype proxytype;
|
proxytypes_t proxytype;
|
||||||
} proxynames[] = {
|
} proxynames[] = {
|
||||||
{ "http:", CURLPROXY_HTTP },
|
{ "http:", PROXY_HTTP },
|
||||||
#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 19) || (LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH >= 4)
|
{ "http0:", PROXY_HTTP_1_0 },
|
||||||
{ "http0:", CURLPROXY_HTTP_1_0 },
|
{ "socks4:", PROXY_SOCKS4 },
|
||||||
#endif
|
{ "socks5:", PROXY_SOCKS5 },
|
||||||
#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 15) || (LIBCURL_VERSION_MINOR == 15 && LIBCURL_VERSION_PATCH >= 2)
|
{ "socks4a:", PROXY_SOCKS4A },
|
||||||
{ "socks4:", CURLPROXY_SOCKS4 },
|
{ "socks5h:", PROXY_SOCKS5H },
|
||||||
#endif
|
|
||||||
{ "socks5:", CURLPROXY_SOCKS5 },
|
|
||||||
#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR >= 18)
|
|
||||||
{ "socks4a:", CURLPROXY_SOCKS4A },
|
|
||||||
{ "socks5h:", CURLPROXY_SOCKS5_HOSTNAME },
|
|
||||||
#endif
|
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *proxytype(curl_proxytype proxytype)
|
const char *proxytype(proxytypes_t proxytype)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -550,7 +559,6 @@ char *get_proxy(char *url, struct pool *pool)
|
|||||||
{
|
{
|
||||||
pool->rpc_proxy = NULL;
|
pool->rpc_proxy = NULL;
|
||||||
|
|
||||||
#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7)
|
|
||||||
char *split;
|
char *split;
|
||||||
int plen, len, i;
|
int plen, len, i;
|
||||||
|
|
||||||
@ -573,7 +581,6 @@ char *get_proxy(char *url, struct pool *pool)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1948,7 +1955,7 @@ static bool setup_stratum_socket(struct pool *pool)
|
|||||||
if (!pool->rpc_proxy && opt_socks_proxy) {
|
if (!pool->rpc_proxy && opt_socks_proxy) {
|
||||||
pool->rpc_proxy = opt_socks_proxy;
|
pool->rpc_proxy = opt_socks_proxy;
|
||||||
extract_sockaddr(pool->rpc_proxy, &pool->sockaddr_proxy_url, &pool->sockaddr_proxy_port);
|
extract_sockaddr(pool->rpc_proxy, &pool->sockaddr_proxy_url, &pool->sockaddr_proxy_port);
|
||||||
pool->rpc_proxytype = CURLPROXY_SOCKS5;
|
pool->rpc_proxytype = PROXY_SOCKS5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->rpc_proxy) {
|
if (pool->rpc_proxy) {
|
||||||
@ -1995,24 +2002,24 @@ static bool setup_stratum_socket(struct pool *pool)
|
|||||||
|
|
||||||
if (pool->rpc_proxy) {
|
if (pool->rpc_proxy) {
|
||||||
switch (pool->rpc_proxytype) {
|
switch (pool->rpc_proxytype) {
|
||||||
case CURLPROXY_HTTP_1_0:
|
case PROXY_HTTP_1_0:
|
||||||
if (!http_negotiate(pool, sockd, true))
|
if (!http_negotiate(pool, sockd, true))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case CURLPROXY_HTTP:
|
case PROXY_HTTP:
|
||||||
if (!http_negotiate(pool, sockd, false))
|
if (!http_negotiate(pool, sockd, false))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case CURLPROXY_SOCKS5:
|
case PROXY_SOCKS5:
|
||||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
case PROXY_SOCKS5H:
|
||||||
if (!socks5_negotiate(pool, sockd))
|
if (!socks5_negotiate(pool, sockd))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case CURLPROXY_SOCKS4:
|
case PROXY_SOCKS4:
|
||||||
if (!socks4_negotiate(pool, sockd, false))
|
if (!socks4_negotiate(pool, sockd, false))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case CURLPROXY_SOCKS4A:
|
case PROXY_SOCKS4A:
|
||||||
if (!socks4_negotiate(pool, sockd, true))
|
if (!socks4_negotiate(pool, sockd, true))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
6
util.h
6
util.h
@ -52,6 +52,12 @@
|
|||||||
#define JSON_LOADS(str, err_ptr) json_loads((str), (err_ptr))
|
#define JSON_LOADS(str, err_ptr) json_loads((str), (err_ptr))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
typedef curl_proxytype proxytypes_t;
|
||||||
|
#else
|
||||||
|
typedef int proxytypes_t;
|
||||||
|
#endif /* HAVE_LIBCURL */
|
||||||
|
|
||||||
/* cgminer specific unnamed semaphore implementations to cope with osx not
|
/* cgminer specific unnamed semaphore implementations to cope with osx not
|
||||||
* implementing them. */
|
* implementing them. */
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
Loading…
Reference in New Issue
Block a user