|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
/*
|
|
|
- * Copyright 2012 Andrew Smith
|
|
|
|
|
|
|
+ * Copyright 2012-2013 Andrew Smith
|
|
|
*
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
@@ -16,6 +16,10 @@
|
|
|
#include "miner.h"
|
|
#include "miner.h"
|
|
|
#include "usbutils.h"
|
|
#include "usbutils.h"
|
|
|
|
|
|
|
|
|
|
+#define NODEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \
|
|
|
|
|
+ (err) == LIBUSB_ERROR_PIPE || \
|
|
|
|
|
+ (err) == LIBUSB_ERROR_OTHER)
|
|
|
|
|
+
|
|
|
#ifdef USE_ICARUS
|
|
#ifdef USE_ICARUS
|
|
|
#define DRV_ICARUS 1
|
|
#define DRV_ICARUS 1
|
|
|
#endif
|
|
#endif
|
|
@@ -161,6 +165,7 @@ static int next_stat = 0;
|
|
|
|
|
|
|
|
static const char **usb_commands;
|
|
static const char **usb_commands;
|
|
|
|
|
|
|
|
|
|
+static const char *C_REJECTED_S = "RejectedNoDevice";
|
|
|
static const char *C_PING_S = "Ping";
|
|
static const char *C_PING_S = "Ping";
|
|
|
static const char *C_CLEAR_S = "Clear";
|
|
static const char *C_CLEAR_S = "Clear";
|
|
|
static const char *C_REQUESTVERSION_S = "RequestVersion";
|
|
static const char *C_REQUESTVERSION_S = "RequestVersion";
|
|
@@ -551,6 +556,7 @@ static void cgusb_check_init()
|
|
|
// 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
|
|
|
// be missalined easily
|
|
// be missalined easily
|
|
|
|
|
+ usb_commands[C_REJECTED] = C_REJECTED_S;
|
|
|
usb_commands[C_PING] = C_PING_S;
|
|
usb_commands[C_PING] = C_PING_S;
|
|
|
usb_commands[C_CLEAR] = C_CLEAR_S;
|
|
usb_commands[C_CLEAR] = C_CLEAR_S;
|
|
|
usb_commands[C_REQUESTVERSION] = C_REQUESTVERSION_S;
|
|
usb_commands[C_REQUESTVERSION] = C_REQUESTVERSION_S;
|
|
@@ -673,8 +679,7 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock)
|
|
|
if (lock)
|
|
if (lock)
|
|
|
mutex_lock(list_lock);
|
|
mutex_lock(list_lock);
|
|
|
|
|
|
|
|
- usb_tmp = usb_head;
|
|
|
|
|
- if (usb_tmp)
|
|
|
|
|
|
|
+ if ((usb_tmp = usb_head))
|
|
|
do {
|
|
do {
|
|
|
if (bus_number == usb_tmp->bus_number
|
|
if (bus_number == usb_tmp->bus_number
|
|
|
&& device_address == usb_tmp->device_address) {
|
|
&& device_address == usb_tmp->device_address) {
|
|
@@ -698,6 +703,8 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock)
|
|
|
if (usb_tmp->next == usb_tmp) {
|
|
if (usb_tmp->next == usb_tmp) {
|
|
|
usb_head = NULL;
|
|
usb_head = NULL;
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ if (usb_head == usb_tmp)
|
|
|
|
|
+ usb_head = usb_tmp->next;
|
|
|
usb_tmp->next->prev = usb_tmp->prev;
|
|
usb_tmp->next->prev = usb_tmp->prev;
|
|
|
usb_tmp->prev->next = usb_tmp->next;
|
|
usb_tmp->prev->next = usb_tmp->next;
|
|
|
}
|
|
}
|
|
@@ -719,13 +726,6 @@ static void release_dev(libusb_device *dev, bool lock)
|
|
|
release(bus_number, device_address, lock);
|
|
release(bus_number, device_address, lock);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#if 0
|
|
|
|
|
-static void release_cgusb(struct cg_usb_device *cgusb, bool lock)
|
|
|
|
|
-{
|
|
|
|
|
- release(cgusb->bus_number, cgusb->device_address, lock);
|
|
|
|
|
-}
|
|
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
|
|
static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
|
|
|
{
|
|
{
|
|
|
if (cgusb->serial_string && cgusb->serial_string != BLANK)
|
|
if (cgusb->serial_string && cgusb->serial_string != BLANK)
|
|
@@ -739,6 +739,8 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb)
|
|
|
|
|
|
|
|
free(cgusb->descriptor);
|
|
free(cgusb->descriptor);
|
|
|
|
|
|
|
|
|
|
+ free(cgusb->found);
|
|
|
|
|
+
|
|
|
free(cgusb);
|
|
free(cgusb);
|
|
|
|
|
|
|
|
return NULL;
|
|
return NULL;
|
|
@@ -751,6 +753,31 @@ void usb_uninit(struct cgpu_info *cgpu)
|
|
|
cgpu->usbdev = free_cgusb(cgpu->usbdev);
|
|
cgpu->usbdev = free_cgusb(cgpu->usbdev);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void release_cgpu(struct cgpu_info *cgpu)
|
|
|
|
|
+{
|
|
|
|
|
+ struct cg_usb_device *cgusb = cgpu->usbdev;
|
|
|
|
|
+ uint8_t bus_number;
|
|
|
|
|
+ uint8_t device_address;
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ cgpu->nodev = true;
|
|
|
|
|
+
|
|
|
|
|
+ // Any devices sharing the same USB device should be marked also
|
|
|
|
|
+ // Currently only MMQ shares a USB device
|
|
|
|
|
+ for (i = 0; i < total_devices; i++)
|
|
|
|
|
+ if (devices[i] != cgpu && devices[i]->usbdev == cgusb) {
|
|
|
|
|
+ devices[i]->nodev = true;
|
|
|
|
|
+ devices[i]->usbdev = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bus_number = cgusb->bus_number;
|
|
|
|
|
+ device_address = cgusb->device_address;
|
|
|
|
|
+
|
|
|
|
|
+ usb_uninit(cgpu);
|
|
|
|
|
+
|
|
|
|
|
+ release(bus_number, device_address, true);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
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)
|
|
|
{
|
|
{
|
|
|
struct cg_usb_device *cgusb = NULL;
|
|
struct cg_usb_device *cgusb = NULL;
|
|
@@ -1172,6 +1199,19 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev
|
|
|
memcpy(&(details->item[item].last), tv_start, sizeof(tv_start));
|
|
memcpy(&(details->item[item].last), tv_start, sizeof(tv_start));
|
|
|
details->item[item].count++;
|
|
details->item[item].count++;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+static void rejected_inc(struct cgpu_info *cgpu)
|
|
|
|
|
+{
|
|
|
|
|
+ struct cg_usb_stats_details *details;
|
|
|
|
|
+ int item = CMD_ERROR;
|
|
|
|
|
+
|
|
|
|
|
+ if (cgpu->usbstat < 1)
|
|
|
|
|
+ newstats(cgpu);
|
|
|
|
|
+
|
|
|
|
|
+ details = &(usb_stats[cgpu->usbstat - 1].details[C_REJECTED * 2 + 0]);
|
|
|
|
|
+
|
|
|
|
|
+ details->item[item].count++;
|
|
|
|
|
+}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd, bool ftdi)
|
|
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd, bool ftdi)
|
|
@@ -1186,6 +1226,15 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
|
|
|
int err, got, tot, i;
|
|
int err, got, tot, i;
|
|
|
bool first = true;
|
|
bool first = true;
|
|
|
|
|
|
|
|
|
|
+ if (cgpu->nodev) {
|
|
|
|
|
+ *buf = '\0';
|
|
|
|
|
+ *processed = 0;
|
|
|
|
|
+#if DO_USB_STATS
|
|
|
|
|
+ rejected_inc(cgpu);
|
|
|
|
|
+#endif
|
|
|
|
|
+ return LIBUSB_ERROR_NO_DEVICE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (timeout == DEVTIMEOUT)
|
|
if (timeout == DEVTIMEOUT)
|
|
|
timeout = usbdev->found->timeout;
|
|
timeout = usbdev->found->timeout;
|
|
|
|
|
|
|
@@ -1212,6 +1261,11 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
|
|
|
|
|
|
|
|
*processed = got;
|
|
*processed = got;
|
|
|
|
|
|
|
|
|
|
+ if (NODEV(err)) {
|
|
|
|
|
+ cgpu->nodev = true;
|
|
|
|
|
+ release_cgpu(cgpu);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1268,6 +1322,11 @@ goteol:
|
|
|
|
|
|
|
|
*processed = tot;
|
|
*processed = tot;
|
|
|
|
|
|
|
|
|
|
+ if (NODEV(err)) {
|
|
|
|
|
+ cgpu->nodev = true;
|
|
|
|
|
+ release_cgpu(cgpu);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1279,6 +1338,14 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
|
|
|
#endif
|
|
#endif
|
|
|
int err, sent;
|
|
int err, sent;
|
|
|
|
|
|
|
|
|
|
+ if (cgpu->nodev) {
|
|
|
|
|
+ *processed = 0;
|
|
|
|
|
+#if DO_USB_STATS
|
|
|
|
|
+ rejected_inc(cgpu);
|
|
|
|
|
+#endif
|
|
|
|
|
+ return LIBUSB_ERROR_NO_DEVICE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
sent = 0;
|
|
sent = 0;
|
|
|
STATS_TIMEVAL(&tv_start);
|
|
STATS_TIMEVAL(&tv_start);
|
|
|
err = libusb_bulk_transfer(usbdev->handle,
|
|
err = libusb_bulk_transfer(usbdev->handle,
|
|
@@ -1291,6 +1358,11 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
|
|
|
|
|
|
|
|
*processed = sent;
|
|
*processed = sent;
|
|
|
|
|
|
|
|
|
|
+ if (NODEV(err)) {
|
|
|
|
|
+ cgpu->nodev = true;
|
|
|
|
|
+ release_cgpu(cgpu);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1302,6 +1374,13 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
|
|
|
#endif
|
|
#endif
|
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
|
|
+ if (cgpu->nodev) {
|
|
|
|
|
+#if DO_USB_STATS
|
|
|
|
|
+ rejected_inc(cgpu);
|
|
|
|
|
+#endif
|
|
|
|
|
+ return LIBUSB_ERROR_NO_DEVICE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
STATS_TIMEVAL(&tv_start);
|
|
STATS_TIMEVAL(&tv_start);
|
|
|
err = libusb_control_transfer(usbdev->handle, request_type,
|
|
err = libusb_control_transfer(usbdev->handle, request_type,
|
|
|
bRequest, wValue, wIndex, NULL, 0,
|
|
bRequest, wValue, wIndex, NULL, 0,
|
|
@@ -1309,6 +1388,11 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
|
|
|
STATS_TIMEVAL(&tv_finish);
|
|
STATS_TIMEVAL(&tv_finish);
|
|
|
USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0);
|
|
USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0);
|
|
|
|
|
|
|
|
|
|
+ if (NODEV(err)) {
|
|
|
|
|
+ cgpu->nodev = true;
|
|
|
|
|
+ release_cgpu(cgpu);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|