Browse Source

Merge branch 'icarus-dev' into usbdev

Conflicts:
	usbutils.h
nfactor-troky
Con Kolivas 12 years ago
parent
commit
876e7e5893
  1. 48
      cgminer.c
  2. 45
      driver-icarus.c
  3. 1
      miner.h
  4. 821
      usbutils.c
  5. 12
      usbutils.h

48
cgminer.c

@ -166,6 +166,7 @@ static int input_thr_id;
int gpur_thr_id; int gpur_thr_id;
static int api_thr_id; static int api_thr_id;
#ifdef USE_USBUTILS #ifdef USE_USBUTILS
static int usbres_thr_id;
static int hotplug_thr_id; static int hotplug_thr_id;
#endif #endif
static int total_control_threads; static int total_control_threads;
@ -177,6 +178,7 @@ int hotplug_time = 5;
#ifdef USE_USBUTILS #ifdef USE_USBUTILS
pthread_mutex_t cgusb_lock; pthread_mutex_t cgusb_lock;
pthread_mutex_t cgusbres_lock;
#endif #endif
pthread_mutex_t hash_lock; pthread_mutex_t hash_lock;
@ -2846,6 +2848,10 @@ static void __kill_work(void)
if (!opt_scrypt) { if (!opt_scrypt) {
applog(LOG_DEBUG, "Releasing all USB devices"); applog(LOG_DEBUG, "Releasing all USB devices");
usb_cleanup(); usb_cleanup();
applog(LOG_DEBUG, "Killing off usbres thread");
thr = &control_thr[usbres_thr_id];
thr_info_cancel(thr);
} }
#endif #endif
@ -7197,6 +7203,7 @@ int main(int argc, char *argv[])
} }
#ifdef USE_USBUTILS #ifdef USE_USBUTILS
mutex_init(&cgusb_lock); mutex_init(&cgusb_lock);
mutex_init(&cgusbres_lock);
#endif #endif
#endif #endif
@ -7323,8 +7330,25 @@ int main(int argc, char *argv[])
/* Use a shorter scantime for scrypt */ /* Use a shorter scantime for scrypt */
if (opt_scantime < 0) if (opt_scantime < 0)
opt_scantime = opt_scrypt ? 30 : 60; opt_scantime = opt_scrypt ? 30 : 60;
total_control_threads = 9;
control_thr = calloc(total_control_threads, sizeof(*thr));
if (!control_thr)
quit(1, "Failed to calloc control_thr");
gwsched_thr_id = 0;
#ifdef USE_USBUTILS #ifdef USE_USBUTILS
usb_initialise(); usb_initialise();
// before device detection
if (!opt_scrypt) {
usbres_thr_id = 1;
thr = &control_thr[usbres_thr_id];
if (thr_info_create(thr, NULL, usb_resource_thread, thr))
quit(1, "usb resource thread create failed");
pthread_detach(thr->pth);
}
#endif #endif
#ifdef HAVE_OPENCL #ifdef HAVE_OPENCL
@ -7464,13 +7488,7 @@ int main(int argc, char *argv[])
quit(1, "Failed to calloc mining_thr[%d]", i); quit(1, "Failed to calloc mining_thr[%d]", i);
} }
total_control_threads = 8; stage_thr_id = 2;
control_thr = calloc(total_control_threads, sizeof(*thr));
if (!control_thr)
quit(1, "Failed to calloc control_thr");
gwsched_thr_id = 0;
stage_thr_id = 1;
thr = &control_thr[stage_thr_id]; thr = &control_thr[stage_thr_id];
thr->q = tq_new(); thr->q = tq_new();
if (!thr->q) if (!thr->q)
@ -7591,14 +7609,14 @@ begin_bench:
cgtime(&total_tv_start); cgtime(&total_tv_start);
cgtime(&total_tv_end); cgtime(&total_tv_end);
watchpool_thr_id = 2; watchpool_thr_id = 3;
thr = &control_thr[watchpool_thr_id]; thr = &control_thr[watchpool_thr_id];
/* start watchpool thread */ /* start watchpool thread */
if (thr_info_create(thr, NULL, watchpool_thread, NULL)) if (thr_info_create(thr, NULL, watchpool_thread, NULL))
quit(1, "watchpool thread create failed"); quit(1, "watchpool thread create failed");
pthread_detach(thr->pth); pthread_detach(thr->pth);
watchdog_thr_id = 3; watchdog_thr_id = 4;
thr = &control_thr[watchdog_thr_id]; thr = &control_thr[watchdog_thr_id];
/* start watchdog thread */ /* start watchdog thread */
if (thr_info_create(thr, NULL, watchdog_thread, NULL)) if (thr_info_create(thr, NULL, watchdog_thread, NULL))
@ -7607,7 +7625,7 @@ begin_bench:
#ifdef HAVE_OPENCL #ifdef HAVE_OPENCL
/* Create reinit gpu thread */ /* Create reinit gpu thread */
gpur_thr_id = 4; gpur_thr_id = 5;
thr = &control_thr[gpur_thr_id]; thr = &control_thr[gpur_thr_id];
thr->q = tq_new(); thr->q = tq_new();
if (!thr->q) if (!thr->q)
@ -7617,14 +7635,14 @@ begin_bench:
#endif #endif
/* Create API socket thread */ /* Create API socket thread */
api_thr_id = 5; api_thr_id = 6;
thr = &control_thr[api_thr_id]; thr = &control_thr[api_thr_id];
if (thr_info_create(thr, NULL, api_thread, thr)) if (thr_info_create(thr, NULL, api_thread, thr))
quit(1, "API thread create failed"); quit(1, "API thread create failed");
#ifdef USE_USBUTILS #ifdef USE_USBUTILS
if (!opt_scrypt) { if (!opt_scrypt) {
hotplug_thr_id = 6; hotplug_thr_id = 7;
thr = &control_thr[hotplug_thr_id]; thr = &control_thr[hotplug_thr_id];
if (thr_info_create(thr, NULL, hotplug_thread, thr)) if (thr_info_create(thr, NULL, hotplug_thread, thr))
quit(1, "hotplug thread create failed"); quit(1, "hotplug thread create failed");
@ -7636,7 +7654,7 @@ begin_bench:
/* Create curses input thread for keyboard input. Create this last so /* Create curses input thread for keyboard input. Create this last so
* that we know all threads are created since this can call kill_work * that we know all threads are created since this can call kill_work
* to try and shut down all previous threads. */ * to try and shut down all previous threads. */
input_thr_id = 7; input_thr_id = 8;
thr = &control_thr[input_thr_id]; thr = &control_thr[input_thr_id];
if (thr_info_create(thr, NULL, input_thread, thr)) if (thr_info_create(thr, NULL, input_thread, thr))
quit(1, "input thread create failed"); quit(1, "input thread create failed");
@ -7644,8 +7662,8 @@ begin_bench:
#endif #endif
/* Just to be sure */ /* Just to be sure */
if (total_control_threads != 8) if (total_control_threads != 9)
quit(1, "incorrect total_control_threads (%d) should be 8", total_control_threads); quit(1, "incorrect total_control_threads (%d) should be 9", total_control_threads);
/* Once everything is set up, main() becomes the getwork scheduler */ /* Once everything is set up, main() becomes the getwork scheduler */
while (42) { while (42) {

45
driver-icarus.c

@ -244,16 +244,18 @@ static void _transfer(struct cgpu_info *icarus, uint8_t request_type, uint8_t bR
#define transfer(icarus, request_type, bRequest, wValue, wIndex, cmd) \ #define transfer(icarus, request_type, bRequest, wValue, wIndex, cmd) \
_transfer(icarus, request_type, bRequest, wValue, wIndex, NULL, 0, cmd) _transfer(icarus, request_type, bRequest, wValue, wIndex, NULL, 0, cmd)
// TODO: handle baud static void icarus_initialise(struct cgpu_info *icarus, int baud)
static void icarus_initialise(struct cgpu_info *icarus, __maybe_unused int baud)
{ {
uint16_t wValue, wIndex;
if (icarus->usbinfo.nodev) if (icarus->usbinfo.nodev)
return; return;
switch (icarus->usbdev->ident) { switch (icarus->usbdev->ident) {
case IDENT_BLT: case IDENT_BLT:
case IDENT_LLT: case IDENT_LLT:
case IDENT_CMR: case IDENT_CMR1:
case IDENT_CMR2:
// Latency // Latency
transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY, FTDI_VALUE_LATENCY, transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY, FTDI_VALUE_LATENCY,
icarus->usbdev->found->interface, C_LATENCY); icarus->usbdev->found->interface, C_LATENCY);
@ -275,9 +277,30 @@ static void icarus_initialise(struct cgpu_info *icarus, __maybe_unused int baud)
if (icarus->usbinfo.nodev) if (icarus->usbinfo.nodev)
return; return;
// default to BLT/LLT 115200
wValue = FTDI_VALUE_BAUD_BLT;
wIndex = FTDI_INDEX_BAUD_BLT;
if (icarus->usbdev->ident == IDENT_CMR1 ||
icarus->usbdev->ident == IDENT_CMR2) {
switch (baud) {
case 115200:
wValue = FTDI_VALUE_BAUD_CMR_115;
wIndex = FTDI_INDEX_BAUD_CMR_115;
break;
case 57600:
wValue = FTDI_VALUE_BAUD_CMR_57;
wIndex = FTDI_INDEX_BAUD_CMR_57;
break;
default:
quit(1, "icarus_intialise() invalid baud (%d) for Cairnsmore1", baud);
break;
}
}
// Set the baud // Set the baud
transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BLT, transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, wValue,
(FTDI_INDEX_BAUD_BLT & 0xff00) | icarus->usbdev->found->interface, (wIndex & 0xff00) | icarus->usbdev->found->interface,
C_SETBAUD); C_SETBAUD);
if (icarus->usbinfo.nodev) if (icarus->usbinfo.nodev)
@ -387,7 +410,7 @@ static int icarus_get_nonce(struct cgpu_info *icarus, unsigned char *buf, struct
err = usb_read_timeout(icarus, (char *)buf, read_amount, &amt, ICARUS_WAIT_TIMEOUT, C_GETRESULTS); err = usb_read_timeout(icarus, (char *)buf, read_amount, &amt, ICARUS_WAIT_TIMEOUT, C_GETRESULTS);
cgtime(&read_finish); cgtime(&read_finish);
if (err < 0 && err != LIBUSB_ERROR_TIMEOUT) { if (err < 0 && err != LIBUSB_ERROR_TIMEOUT) {
applog(LOG_ERR, "%s%i: Comms error (err=%d amt=%d)", applog(LOG_ERR, "%s%i: Comms error (rerr=%d amt=%d)",
icarus->drv->name, icarus->device_id, err, amt); icarus->drv->name, icarus->device_id, err, amt);
dev_error(icarus, REASON_DEV_COMMS_ERROR); dev_error(icarus, REASON_DEV_COMMS_ERROR);
return ICA_NONCE_ERROR; return ICA_NONCE_ERROR;
@ -484,7 +507,9 @@ 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;
case IDENT_CMR: // TODO: ?
case IDENT_CMR1:
case IDENT_CMR2:
info->Hs = CAIRNSMORE1_HASH_TIME; info->Hs = CAIRNSMORE1_HASH_TIME;
break; break;
default: default:
@ -617,7 +642,9 @@ 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;
case IDENT_CMR: // TODO: ?
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;
@ -860,7 +887,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
err = usb_write(icarus, (char *)ob_bin, sizeof(ob_bin), &amount, C_SENDWORK); err = usb_write(icarus, (char *)ob_bin, sizeof(ob_bin), &amount, C_SENDWORK);
if (err < 0 || amount != sizeof(ob_bin)) { if (err < 0 || amount != sizeof(ob_bin)) {
applog(LOG_ERR, "%s%i: Comms error (err=%d amt=%d)", applog(LOG_ERR, "%s%i: Comms error (werr=%d amt=%d)",
icarus->drv->name, icarus->device_id, err, amount); icarus->drv->name, icarus->device_id, err, amount);
dev_error(icarus, REASON_DEV_COMMS_ERROR); dev_error(icarus, REASON_DEV_COMMS_ERROR);
icarus_initialise(icarus, info->baud); icarus_initialise(icarus, info->baud);

1
miner.h

@ -880,6 +880,7 @@ extern int opt_expiry;
#ifdef USE_USBUTILS #ifdef USE_USBUTILS
extern pthread_mutex_t cgusb_lock; extern pthread_mutex_t cgusb_lock;
extern pthread_mutex_t cgusbres_lock;
#endif #endif
extern cglock_t control_lock; extern cglock_t control_lock;

821
usbutils.c

@ -106,7 +106,24 @@ static struct usb_endpoints llt_eps[] = {
{ 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 cmr_eps[] = { static struct usb_endpoints cmr1_eps[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 }
/*
Interface 1
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(4), 0 },
Interface 2
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(5), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(6), 0 },
Interface 3
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(7), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(8), 0 }
*/
};
static struct usb_endpoints cmr2_eps[] = {
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 },
{ LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 }
}; };
@ -230,7 +247,7 @@ static struct usb_find_devices find_dev[] = {
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
.name = "CMR", .name = "CMR",
.ident = IDENT_CMR, .ident = IDENT_CMR1,
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x8350, .idProduct = 0x8350,
.iProduct = "Cairnsmore1", .iProduct = "Cairnsmore1",
@ -238,12 +255,12 @@ static struct usb_find_devices find_dev[] = {
.config = 1, .config = 1,
.interface = 0, .interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.epcount = ARRAY_SIZE(cmr_eps), .epcount = ARRAY_SIZE(cmr1_eps),
.eps = cmr_eps }, .eps = cmr1_eps },
{ {
.drv = DRV_ICARUS, .drv = DRV_ICARUS,
.name = "CMR", .name = "CMR",
.ident = IDENT_CMR, .ident = IDENT_CMR2,
.idVendor = IDVENDOR_FTDI, .idVendor = IDVENDOR_FTDI,
.idProduct = 0x6014, .idProduct = 0x6014,
.iProduct = "Cairnsmore1", .iProduct = "Cairnsmore1",
@ -251,8 +268,8 @@ static struct usb_find_devices find_dev[] = {
.config = 1, .config = 1,
.interface = 0, .interface = 0,
.timeout = ICARUS_TIMEOUT_MS, .timeout = ICARUS_TIMEOUT_MS,
.epcount = ARRAY_SIZE(cmr_eps), .epcount = ARRAY_SIZE(cmr2_eps),
.eps = cmr_eps }, .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
@ -319,6 +336,8 @@ static struct driver_count {
static struct usb_busdev { static struct usb_busdev {
int bus_number; int bus_number;
int device_address; int device_address;
void *resource1;
void *resource2;
} *busdev; } *busdev;
static int busdev_count = 0; static int busdev_count = 0;
@ -336,6 +355,27 @@ struct usb_in_use_list {
// List of in use devices // List of in use devices
static struct usb_in_use_list *in_use_head = NULL; static struct usb_in_use_list *in_use_head = NULL;
struct resource_work {
bool lock;
const char *dname;
uint8_t bus_number;
uint8_t device_address;
struct resource_work *next;
};
// Pending work for the reslock thread
struct resource_work *res_work_head = NULL;
struct resource_reply {
uint8_t bus_number;
uint8_t device_address;
bool got;
struct resource_reply *next;
};
// Replies to lock requests
struct resource_reply *res_reply_head = NULL;
// Set this to 0 to remove stats processing // Set this to 0 to remove stats processing
#define DO_USB_STATS 1 #define DO_USB_STATS 1
@ -627,6 +667,8 @@ static void append(char **buf, char *append, size_t *off, size_t *len)
{ {
*len *= 2; *len *= 2;
*buf = realloc(*buf, *len); *buf = realloc(*buf, *len);
if (unlikely(!*buf))
quit(1, "USB failed to realloc append");
} }
strcpy(*buf + *off, append); strcpy(*buf + *off, append);
@ -840,6 +882,8 @@ void usb_all(int level)
{ {
len = 10000; len = 10000;
buf = malloc(len+1); buf = malloc(len+1);
if (unlikely(!buf))
quit(1, "USB failed to malloc buf in usb_all");
sprintf(buf, "USB all: found %d devices", (int)count); sprintf(buf, "USB all: found %d devices", (int)count);
off = strlen(buf); off = strlen(buf);
@ -878,6 +922,8 @@ static void cgusb_check_init()
} }
usb_commands = malloc(sizeof(*usb_commands) * C_MAX); usb_commands = malloc(sizeof(*usb_commands) * C_MAX);
if (unlikely(!usb_commands))
quit(1, "USB failed to malloc usb_commands");
// use constants so the stat generation is very quick // use constants so the stat generation is very quick
// and the association between number and name can't // and the association between number and name can't
@ -968,6 +1014,80 @@ void usb_applog(struct cgpu_info *cgpu, enum usb_cmds cmd, char *msg, int amount
err, amount); err, amount);
} }
#ifdef WIN32
static void in_use_store_ress(uint8_t bus_number, uint8_t device_address, void *resource1, void *resource2)
{
struct usb_in_use_list *in_use_tmp;
bool found = false, empty = true;
mutex_lock(&cgusb_lock);
in_use_tmp = in_use_head;
while (in_use_tmp) {
if (in_use_tmp->in_use.bus_number == (int)bus_number &&
in_use_tmp->in_use.device_address == (int)device_address) {
found = true;
if (in_use_tmp->in_use.resource1)
empty = false;
in_use_tmp->in_use.resource1 = resource1;
if (in_use_tmp->in_use.resource2)
empty = false;
in_use_tmp->in_use.resource2 = resource2;
break;
}
in_use_tmp = in_use_tmp->next;
}
mutex_unlock(&cgusb_lock);
if (found == false)
applog(LOG_ERR, "FAIL: USB store_ress not found (%d:%d)",
(int)bus_number, (int)device_address);
if (empty == false)
applog(LOG_ERR, "FAIL: USB store_ress not empty (%d:%d)",
(int)bus_number, (int)device_address);
}
static void in_use_get_ress(uint8_t bus_number, uint8_t device_address, void **resource1, void **resource2)
{
struct usb_in_use_list *in_use_tmp;
bool found = false, empty = false;
mutex_lock(&cgusb_lock);
in_use_tmp = in_use_head;
while (in_use_tmp) {
if (in_use_tmp->in_use.bus_number == (int)bus_number &&
in_use_tmp->in_use.device_address == (int)device_address) {
found = true;
if (!in_use_tmp->in_use.resource1)
empty = true;
*resource1 = in_use_tmp->in_use.resource1;
in_use_tmp->in_use.resource1 = NULL;
if (!in_use_tmp->in_use.resource2)
empty = true;
*resource2 = in_use_tmp->in_use.resource2;
in_use_tmp->in_use.resource2 = NULL;
break;
}
in_use_tmp = in_use_tmp->next;
}
mutex_unlock(&cgusb_lock);
if (found == false)
applog(LOG_ERR, "FAIL: USB get_lock not found (%d:%d)",
(int)bus_number, (int)device_address);
if (empty == true)
applog(LOG_ERR, "FAIL: USB get_lock empty (%d:%d)",
(int)bus_number, (int)device_address);
}
#endif
static bool __is_in_use(uint8_t bus_number, uint8_t device_address) static bool __is_in_use(uint8_t bus_number, uint8_t device_address)
{ {
struct usb_in_use_list *in_use_tmp; struct usb_in_use_list *in_use_tmp;
@ -1013,6 +1133,8 @@ static void add_in_use(uint8_t bus_number, uint8_t device_address)
} }
in_use_tmp = calloc(1, sizeof(*in_use_tmp)); in_use_tmp = calloc(1, sizeof(*in_use_tmp));
if (unlikely(!in_use_tmp))
quit(1, "USB failed to calloc in_use_tmp");
in_use_tmp->in_use.bus_number = (int)bus_number; in_use_tmp->in_use.bus_number = (int)bus_number;
in_use_tmp->in_use.device_address = (int)device_address; in_use_tmp->in_use.device_address = (int)device_address;
in_use_tmp->next = in_use_head; in_use_tmp->next = in_use_head;
@ -1061,178 +1183,63 @@ static void remove_in_use(uint8_t bus_number, uint8_t device_address)
(int)bus_number, (int)device_address); (int)bus_number, (int)device_address);
} }
#ifndef WIN32
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
union semun {
int sem;
struct semid_ds *seminfo;
ushort *all;
};
#endif
// Any errors should always be printed since they will rarely if ever occur
// and thus it is best to always display them
static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
{ {
applog(LOG_DEBUG, "USB lock %s %d-%d", drv->name, (int)bus_number, (int)device_address); struct resource_work *res_work;
bool ret;
#ifdef WIN32 applog(LOG_DEBUG, "USB lock %s %d-%d", drv->dname, (int)bus_number, (int)device_address);
struct cgpu_info *cgpu;
HANDLE usbMutex;
char name[64];
DWORD res;
int i;
if (is_in_use_bd(bus_number, device_address)) res_work = calloc(1, sizeof(*res_work));
return false; if (unlikely(!res_work))
quit(1, "USB failed to calloc lock res_work");
res_work->lock = true;
res_work->dname = (const char *)(drv->dname);
res_work->bus_number = bus_number;
res_work->device_address = device_address;
sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address); mutex_lock(&cgusbres_lock);
usbMutex = CreateMutex(NULL, FALSE, name); res_work->next = res_work_head;
if (usbMutex == NULL) { res_work_head = res_work;
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' err (%d)",
drv->dname, name, GetLastError());
return false;
}
res = WaitForSingleObject(usbMutex, 0); mutex_unlock(&cgusbres_lock);
switch(res) {
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
// Am I using it already?
for (i = 0; i < total_devices; i++) {
cgpu = get_devices(i);
if (cgpu->usbinfo.bus_number == bus_number &&
cgpu->usbinfo.device_address == device_address &&
cgpu->usbinfo.nodev == false) {
if (ReleaseMutex(usbMutex)) {
applog(LOG_WARNING,
"MTX: %s USB can't get '%s' - device in use",
drv->dname, name);
goto fail;
}
applog(LOG_ERR,
"MTX: %s USB can't get '%s' - device in use - failure (%d)",
drv->dname, name, GetLastError());
goto fail;
}
}
add_in_use(bus_number, device_address);
return true;
case WAIT_TIMEOUT:
if (!hotplug_mode)
applog(LOG_WARNING,
"MTX: %s USB failed to get '%s' - device in use",
drv->dname, name);
goto fail;
case WAIT_FAILED:
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' err (%d)",
drv->dname, name, GetLastError());
goto fail;
default:
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' unknown reply (%d)",
drv->dname, name, res);
goto fail;
}
CloseHandle(usbMutex); nmsleep(46);
add_in_use(bus_number, device_address);
return true;
fail:
CloseHandle(usbMutex);
return false;
#else
struct semid_ds seminfo;
union semun opt;
char name[64];
key_t key;
int fd, sem, count;
if (is_in_use_bd(bus_number, device_address)) // TODO: add a timeout fail - restart the resource thread?
return false; while (true) {
mutex_lock(&cgusbres_lock);
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address); if (res_reply_head) {
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); struct resource_reply *res_reply_prev = NULL;
if (fd == -1) { struct resource_reply *res_reply = res_reply_head;
applog(LOG_ERR, while (res_reply) {
"SEM: %s USB open failed '%s' err (%d) %s", if (res_reply->bus_number == bus_number &&
drv->dname, name, errno, strerror(errno)); res_reply->device_address == device_address) {
return false;
}
close(fd);
key = ftok(name, 'K');
sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 438);
if (sem < 0) {
if (errno != EEXIST) {
applog(LOG_ERR,
"SEM: %s USB failed to get '%s' err (%d) %s",
drv->dname, name, errno, strerror(errno));
return false;
}
sem = semget(key, 1, 0); if (res_reply_prev)
if (sem < 0) { res_reply_prev->next = res_reply->next;
applog(LOG_ERR, else
"SEM: %s USB failed to access '%s' err (%d) %s", res_reply_head = res_reply->next;
drv->dname, name, errno, strerror(errno));
return false;
}
opt.seminfo = &seminfo; mutex_unlock(&cgusbres_lock);
count = 0;
while (++count) { ret = res_reply->got;
// Should NEVER take 100ms
if (count > 99) { free(res_reply);
applog(LOG_ERR,
"SEM: %s USB timeout waiting for (%d) '%s'", return ret;
drv->dname, sem, name);
return false;
}
if (semctl(sem, 0, IPC_STAT, opt) == -1) {
applog(LOG_ERR,
"SEM: %s USB failed to wait for (%d) '%s' count %d err (%d) %s",
drv->dname, sem, name, count, errno, strerror(errno));
return false;
} }
if (opt.seminfo->sem_otime != 0) res_reply_prev = res_reply;
break; res_reply = res_reply->next;
nmsleep(1);
} }
} }
struct sembuf sops[] = { mutex_unlock(&cgusbres_lock);
{ 0, 0, IPC_NOWAIT | SEM_UNDO },
{ 0, 1, IPC_NOWAIT | SEM_UNDO }
};
if (semop(sem, sops, 2)) { nmsleep(45);
if (errno == EAGAIN) {
if (!hotplug_mode)
applog(LOG_WARNING,
"SEM: %s USB failed to get (%d) '%s' - device in use",
drv->dname, sem, name);
} else {
applog(LOG_DEBUG,
"SEM: %s USB failed to get (%d) '%s' err (%d) %s",
drv->dname, sem, name, errno, strerror(errno));
}
return false;
} }
add_in_use(bus_number, device_address);
return true;
#endif
} }
static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev)
@ -1240,89 +1247,41 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev)
return cgminer_usb_lock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev)); return cgminer_usb_lock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev));
} }
// Any errors should always be printed since they will rarely if ever occur
// and thus it is best to always display them
static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
{ {
applog(LOG_DEBUG, "USB unlock %s %d-%d", drv->name, (int)bus_number, (int)device_address); struct resource_work *res_work;
#ifdef WIN32 applog(LOG_DEBUG, "USB unlock %s %d-%d", drv->dname, (int)bus_number, (int)device_address);
HANDLE usbMutex;
char name[64];
sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address); res_work = calloc(1, sizeof(*res_work));
if (unlikely(!res_work))
quit(1, "USB failed to calloc unlock res_work");
res_work->lock = false;
res_work->dname = (const char *)(drv->dname);
res_work->bus_number = bus_number;
res_work->device_address = device_address;
usbMutex = CreateMutex(NULL, FALSE, name); mutex_lock(&cgusbres_lock);
if (usbMutex == NULL) {
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' for release err (%d)",
drv->dname, name, GetLastError());
return;
}
if (!ReleaseMutex(usbMutex)) res_work->next = res_work_head;
applog(LOG_ERR, res_work_head = res_work;
"MTX: %s USB failed to release '%s' err (%d)",
drv->dname, name, GetLastError());
CloseHandle(usbMutex); mutex_unlock(&cgusbres_lock);
remove_in_use(bus_number, device_address);
return;
#else
char name[64];
key_t key;
int fd, sem;
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd == -1) {
applog(LOG_ERR,
"SEM: %s USB open failed '%s' for release err (%d) %s",
drv->dname, name, errno, strerror(errno));
return; return;
} }
close(fd);
key = ftok(name, 'K');
sem = semget(key, 1, 0); static void cgminer_usb_unlock(struct device_drv *drv, libusb_device *dev)
if (sem < 0) { {
applog(LOG_ERR, cgminer_usb_unlock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev));
"SEM: %s USB failed to get '%s' for release err (%d) %s",
drv->dname, name, errno, strerror(errno));
return;
} }
struct sembuf sops[] = { static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
{ 0, -1, SEM_UNDO } {
}; applog(LOG_DEBUG, "USB free %s", cgusb->found->name);
// Allow a 10ms timeout if (cgusb->serial_string && cgusb->serial_string != BLANK)
// exceeding this timeout means it would probably never succeed anyway free(cgusb->serial_string);
struct timespec timeout = { 0, 10000000 };
// Wait forever since we shoud be the one who has it
if (semtimedop(sem, sops, 1, &timeout)) {
applog(LOG_ERR,
"SEM: %s USB failed to release '%s' err (%d) %s",
drv->dname, name, errno, strerror(errno));
}
remove_in_use(bus_number, device_address);
return;
#endif
}
static void cgminer_usb_unlock(struct device_drv *drv, libusb_device *dev)
{
cgminer_usb_unlock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev));
}
static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
{
applog(LOG_DEBUG, "USB free %s", cgusb->found->name);
if (cgusb->serial_string && cgusb->serial_string != BLANK)
free(cgusb->serial_string);
if (cgusb->manuf_string && cgusb->manuf_string != BLANK) if (cgusb->manuf_string && cgusb->manuf_string != BLANK)
free(cgusb->manuf_string); free(cgusb->manuf_string);
@ -1416,6 +1375,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address);
cgusb = calloc(1, sizeof(*cgusb)); cgusb = calloc(1, sizeof(*cgusb));
if (unlikely(!cgusb))
quit(1, "USB failed to calloc _usb_init cgusb");
cgusb->found = found; cgusb->found = found;
if (found->idVendor == IDVENDOR_FTDI) if (found->idVendor == IDVENDOR_FTDI)
@ -1424,6 +1385,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
cgusb->ident = found->ident; cgusb->ident = found->ident;
cgusb->descriptor = calloc(1, sizeof(*(cgusb->descriptor))); cgusb->descriptor = calloc(1, sizeof(*(cgusb->descriptor)));
if (unlikely(!cgusb->descriptor))
quit(1, "USB failed to calloc _usb_init cgusb descriptor");
err = libusb_get_device_descriptor(dev, cgusb->descriptor); err = libusb_get_device_descriptor(dev, cgusb->descriptor);
if (err) { if (err) {
@ -1724,6 +1687,8 @@ static struct usb_find_devices *usb_check_each(int drvnum, struct device_drv *dr
if (find_dev[i].drv == drvnum) { if (find_dev[i].drv == drvnum) {
if (usb_check_device(drv, dev, &(find_dev[i]))) { if (usb_check_device(drv, dev, &(find_dev[i]))) {
found = malloc(sizeof(*found)); found = malloc(sizeof(*found));
if (unlikely(!found))
quit(1, "USB failed to malloc found");
memcpy(found, &(find_dev[i]), sizeof(*found)); memcpy(found, &(find_dev[i]), sizeof(*found));
return found; return found;
} }
@ -1961,13 +1926,13 @@ static void newstats(struct cgpu_info *cgpu)
mutex_unlock(&cgusb_lock); mutex_unlock(&cgusb_lock);
usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat);
if (!usb_stats) if (unlikely(!usb_stats))
quit(1, "USB failed to realloc usb_stats %d", next_stat); quit(1, "USB failed to realloc usb_stats %d", next_stat);
usb_stats[next_stat-1].name = cgpu->drv->name; usb_stats[next_stat-1].name = cgpu->drv->name;
usb_stats[next_stat-1].device_id = -1; usb_stats[next_stat-1].device_id = -1;
usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2); usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2);
if (!usb_stats[next_stat-1].details) if (unlikely(!usb_stats[next_stat-1].details))
quit(1, "USB failed to calloc details for %d", next_stat); quit(1, "USB failed to calloc details for %d", next_stat);
for (i = 1; i < C_MAX * 2; i += 2) for (i = 1; i < C_MAX * 2; i += 2)
@ -2474,6 +2439,8 @@ void usb_initialise()
} }
busdev = realloc(busdev, sizeof(*busdev) * (++busdev_count)); busdev = realloc(busdev, sizeof(*busdev) * (++busdev_count));
if (unlikely(!busdev))
quit(1, "USB failed to realloc busdev");
busdev[busdev_count-1].bus_number = bus; busdev[busdev_count-1].bus_number = bus;
busdev[busdev_count-1].device_address = dev; busdev[busdev_count-1].device_address = dev;
@ -2542,3 +2509,393 @@ void usb_initialise()
} }
} }
} }
#ifndef WIN32
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
union semun {
int sem;
struct semid_ds *seminfo;
ushort *all;
};
#else
static LPSECURITY_ATTRIBUTES unsec(LPSECURITY_ATTRIBUTES sec)
{
FreeSid(((PSECURITY_DESCRIPTOR)(sec->lpSecurityDescriptor))->Group);
free(sec->lpSecurityDescriptor);
free(sec);
return NULL;
}
static LPSECURITY_ATTRIBUTES mksec(const char *dname, uint8_t bus_number, uint8_t device_address)
{
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = {SECURITY_WORLD_SID_AUTHORITY};
PSID gsid = NULL;
LPSECURITY_ATTRIBUTES sec_att = NULL;
PSECURITY_DESCRIPTOR sec_des = NULL;
sec_des = malloc(sizeof(*sec_des));
if (unlikely(!sec_des))
quit(1, "MTX: Failed to malloc LPSECURITY_DESCRIPTOR");
if (!InitializeSecurityDescriptor(sec_des, SECURITY_DESCRIPTOR_REVISION)) {
applog(LOG_ERR,
"MTX: %s (%d:%d) USB failed to init secdes err (%d)",
dname, (int)bus_number, (int)device_address,
GetLastError());
free(sec_des);
return NULL;
}
if (!SetSecurityDescriptorDacl(sec_des, TRUE, NULL, FALSE)) {
applog(LOG_ERR,
"MTX: %s (%d:%d) USB failed to secdes dacl err (%d)",
dname, (int)bus_number, (int)device_address,
GetLastError());
free(sec_des);
return NULL;
}
if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &gsid)) {
applog(LOG_ERR,
"MTX: %s (%d:%d) USB failed to create gsid err (%d)",
dname, (int)bus_number, (int)device_address,
GetLastError());
free(sec_des);
return NULL;
}
if (!SetSecurityDescriptorGroup(sec_des, gsid, FALSE)) {
applog(LOG_ERR,
"MTX: %s (%d:%d) USB failed to secdes grp err (%d)",
dname, (int)bus_number, (int)device_address,
GetLastError());
FreeSid(gsid);
free(sec_des);
return NULL;
}
sec_att = malloc(sizeof(*sec_att));
if (unlikely(!sec_att))
quit(1, "MTX: Failed to malloc LPSECURITY_ATTRIBUTES");
sec_att->nLength = sizeof(*sec_att);
sec_att->lpSecurityDescriptor = sec_des;
sec_att->bInheritHandle = FALSE;
return sec_att;
}
#endif
// Any errors should always be printed since they will rarely if ever occur
// and thus it is best to always display them
static bool resource_lock(const char *dname, uint8_t bus_number, uint8_t device_address)
{
applog(LOG_DEBUG, "USB res lock %s %d-%d", dname, (int)bus_number, (int)device_address);
#ifdef WIN32
struct cgpu_info *cgpu;
LPSECURITY_ATTRIBUTES sec;
HANDLE usbMutex;
char name[64];
DWORD res;
int i;
if (is_in_use_bd(bus_number, device_address))
return false;
sprintf(name, "cg-usb-%d-%d", (int)bus_number, (int)device_address);
sec = mksec(dname, bus_number, device_address);
if (!sec)
return false;
usbMutex = CreateMutex(sec, FALSE, name);
if (usbMutex == NULL) {
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' err (%d)",
dname, name, GetLastError());
sec = unsec(sec);
return false;
}
res = WaitForSingleObject(usbMutex, 0);
switch(res) {
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
// Am I using it already?
for (i = 0; i < total_devices; i++) {
cgpu = get_devices(i);
if (cgpu->usbinfo.bus_number == bus_number &&
cgpu->usbinfo.device_address == device_address &&
cgpu->usbinfo.nodev == false) {
if (ReleaseMutex(usbMutex)) {
applog(LOG_WARNING,
"MTX: %s USB can't get '%s' - device in use",
dname, name);
goto fail;
}
applog(LOG_ERR,
"MTX: %s USB can't get '%s' - device in use - failure (%d)",
dname, name, GetLastError());
goto fail;
}
}
break;
case WAIT_TIMEOUT:
if (!hotplug_mode)
applog(LOG_WARNING,
"MTX: %s USB failed to get '%s' - device in use",
dname, name);
goto fail;
case WAIT_FAILED:
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' err (%d)",
dname, name, GetLastError());
goto fail;
default:
applog(LOG_ERR,
"MTX: %s USB failed to get '%s' unknown reply (%d)",
dname, name, res);
goto fail;
}
add_in_use(bus_number, device_address);
in_use_store_ress(bus_number, device_address, (void *)usbMutex, (void *)sec);
return true;
fail:
CloseHandle(usbMutex);
sec = unsec(sec);
return false;
#else
struct semid_ds seminfo;
union semun opt;
char name[64];
key_t key;
int fd, sem, count;
if (is_in_use_bd(bus_number, device_address))
return false;
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd == -1) {
applog(LOG_ERR,
"SEM: %s USB open failed '%s' err (%d) %s",
dname, name, errno, strerror(errno));
return false;
}
close(fd);
key = ftok(name, 'K');
sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 438);
if (sem < 0) {
if (errno != EEXIST) {
applog(LOG_ERR,
"SEM: %s USB failed to get '%s' err (%d) %s",
dname, name, errno, strerror(errno));
return false;
}
sem = semget(key, 1, 0);
if (sem < 0) {
applog(LOG_ERR,
"SEM: %s USB failed to access '%s' err (%d) %s",
dname, name, errno, strerror(errno));
return false;
}
opt.seminfo = &seminfo;
count = 0;
while (++count) {
// Should NEVER take 100ms
if (count > 99) {
applog(LOG_ERR,
"SEM: %s USB timeout waiting for (%d) '%s'",
dname, sem, name);
return false;
}
if (semctl(sem, 0, IPC_STAT, opt) == -1) {
applog(LOG_ERR,
"SEM: %s USB failed to wait for (%d) '%s' count %d err (%d) %s",
dname, sem, name, count, errno, strerror(errno));
return false;
}
if (opt.seminfo->sem_otime != 0)
break;
nmsleep(1);
}
}
struct sembuf sops[] = {
{ 0, 0, IPC_NOWAIT | SEM_UNDO },
{ 0, 1, IPC_NOWAIT | SEM_UNDO }
};
if (semop(sem, sops, 2)) {
if (errno == EAGAIN) {
if (!hotplug_mode)
applog(LOG_WARNING,
"SEM: %s USB failed to get (%d) '%s' - device in use",
dname, sem, name);
} else {
applog(LOG_DEBUG,
"SEM: %s USB failed to get (%d) '%s' err (%d) %s",
dname, sem, name, errno, strerror(errno));
}
return false;
}
add_in_use(bus_number, device_address);
return true;
#endif
}
// Any errors should always be printed since they will rarely if ever occur
// and thus it is best to always display them
static void resource_unlock(const char *dname, uint8_t bus_number, uint8_t device_address)
{
applog(LOG_DEBUG, "USB res unlock %s %d-%d", dname, (int)bus_number, (int)device_address);
#ifdef WIN32
LPSECURITY_ATTRIBUTES sec = NULL;
HANDLE usbMutex = NULL;
char name[64];
sprintf(name, "cg-usb-%d-%d", (int)bus_number, (int)device_address);
in_use_get_ress(bus_number, device_address, (void **)(&usbMutex), (void **)(&sec));
if (!usbMutex || !sec)
goto fila;
if (!ReleaseMutex(usbMutex))
applog(LOG_ERR,
"MTX: %s USB failed to release '%s' err (%d)",
dname, name, GetLastError());
fila:
if (usbMutex)
CloseHandle(usbMutex);
if (sec)
unsec(sec);
remove_in_use(bus_number, device_address);
return;
#else
char name[64];
key_t key;
int fd, sem;
sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd == -1) {
applog(LOG_ERR,
"SEM: %s USB open failed '%s' for release err (%d) %s",
dname, name, errno, strerror(errno));
return;
}
close(fd);
key = ftok(name, 'K');
sem = semget(key, 1, 0);
if (sem < 0) {
applog(LOG_ERR,
"SEM: %s USB failed to get '%s' for release err (%d) %s",
dname, name, errno, strerror(errno));
return;
}
struct sembuf sops[] = {
{ 0, -1, SEM_UNDO }
};
// Allow a 10ms timeout
// exceeding this timeout means it would probably never succeed anyway
struct timespec timeout = { 0, 10000000 };
// Wait forever since we shoud be the one who has it
if (semtimedop(sem, sops, 1, &timeout)) {
applog(LOG_ERR,
"SEM: %s USB failed to release '%s' err (%d) %s",
dname, name, errno, strerror(errno));
}
remove_in_use(bus_number, device_address);
return;
#endif
}
static void resource_process()
{
struct resource_work *res_work = NULL;
struct resource_reply *res_reply = NULL;
bool ok;
applog(LOG_DEBUG, "RES: %s (%d:%d) lock=%d",
res_work_head->dname,
(int)res_work_head->bus_number,
(int)res_work_head->device_address,
res_work_head->lock);
if (res_work_head->lock) {
ok = resource_lock(res_work_head->dname,
res_work_head->bus_number,
res_work_head->device_address);
applog(LOG_DEBUG, "RES: %s (%d:%d) lock ok=%d",
res_work_head->dname,
(int)res_work_head->bus_number,
(int)res_work_head->device_address,
ok);
res_reply = calloc(1, sizeof(*res_reply));
if (unlikely(!res_reply))
quit(1, "USB failed to calloc res_reply");
res_reply->bus_number = res_work_head->bus_number;
res_reply->device_address = res_work_head->device_address;
res_reply->got = ok;
res_reply->next = res_reply_head;
res_reply_head = res_reply;
}
else
resource_unlock(res_work_head->dname,
res_work_head->bus_number,
res_work_head->device_address);
res_work = res_work_head;
res_work_head = res_work_head->next;
free(res_work);
}
void *usb_resource_thread(void __maybe_unused *userdata)
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
RenameThread("usbresource");
applog(LOG_DEBUG, "RES: thread starting");
while (0*1337+1) {
mutex_lock(&cgusbres_lock);
while (res_work_head)
resource_process();
mutex_unlock(&cgusbres_lock);
nmsleep(45);
}
return NULL;
}

12
usbutils.h

@ -41,11 +41,19 @@
#define FTDI_VALUE_BAUD_BLT 0x001a #define FTDI_VALUE_BAUD_BLT 0x001a
#define FTDI_INDEX_BAUD_BLT 0x0000 #define FTDI_INDEX_BAUD_BLT 0x0000
// Avalon
#define FTDI_VALUE_BAUD_AVA 0x001A #define FTDI_VALUE_BAUD_AVA 0x001A
#define FTDI_INDEX_BAUD_AVA 0x0000 #define FTDI_INDEX_BAUD_AVA 0x0000
#define FTDI_VALUE_DATA_AVA 8 #define FTDI_VALUE_DATA_AVA 8
// CMR = 115200 & 57600
#define FTDI_VALUE_BAUD_CMR_115 0xc068
#define FTDI_INDEX_BAUD_CMR_115 0x0200
#define FTDI_VALUE_BAUD_CMR_57 0x80d0
#define FTDI_INDEX_BAUD_CMR_57 0x0200
// Data control // Data control
#define FTDI_VALUE_DATA_BFL 0 #define FTDI_VALUE_DATA_BFL 0
#define FTDI_VALUE_DATA_BAS FTDI_VALUE_DATA_BFL #define FTDI_VALUE_DATA_BAS FTDI_VALUE_DATA_BFL
@ -114,7 +122,8 @@ enum sub_ident {
IDENT_AMU, IDENT_AMU,
IDENT_BLT, IDENT_BLT,
IDENT_LLT, IDENT_LLT,
IDENT_CMR, IDENT_CMR1,
IDENT_CMR2,
IDENT_ZTX IDENT_ZTX
}; };
@ -244,6 +253,7 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, char *buf, int bufsiz, int *amount, unsigned int timeout, enum usb_cmds cmd); int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, char *buf, int bufsiz, int *amount, unsigned int timeout, enum usb_cmds cmd);
void usb_cleanup(); void usb_cleanup();
void usb_initialise(); void usb_initialise();
void *usb_resource_thread(void *userdata);
#define usb_read(cgpu, buf, bufsiz, read, cmd) \ #define usb_read(cgpu, buf, bufsiz, read, cmd) \
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false) _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false)

Loading…
Cancel
Save