|
|
@ -1311,6 +1311,9 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) |
|
|
|
|
|
|
|
|
|
|
|
free(cgusb->found); |
|
|
|
free(cgusb->found); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cgusb->buffer) |
|
|
|
|
|
|
|
free(cgusb->buffer); |
|
|
|
|
|
|
|
|
|
|
|
free(cgusb); |
|
|
|
free(cgusb); |
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
@ -2024,6 +2027,36 @@ static void rejected_inc(struct cgpu_info *cgpu, uint32_t mode) |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *find_end(unsigned char *buf, unsigned char *ptr, int ptrlen, int tot, char *end, int endlen, bool first) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
unsigned char *search; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (endlen > tot) |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If end is only 1 char - do a faster search
|
|
|
|
|
|
|
|
if (endlen == 1) { |
|
|
|
|
|
|
|
if (first) |
|
|
|
|
|
|
|
search = buf; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
search = ptr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return strchr((char *)search, *end); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (first) |
|
|
|
|
|
|
|
search = buf; |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
// must allow end to have been chopped in 2
|
|
|
|
|
|
|
|
if ((tot - ptrlen) >= (endlen - 1)) |
|
|
|
|
|
|
|
search = ptr - (endlen - 1); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
search = ptr - (tot - ptrlen); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return strstr((char *)search, end); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define USB_MAX_READ 8192 |
|
|
|
#define USB_MAX_READ 8192 |
|
|
|
|
|
|
|
|
|
|
|
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, __maybe_unused enum usb_cmds cmd, bool readonce) |
|
|
|
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, const char *end, __maybe_unused enum usb_cmds cmd, bool readonce) |
|
|
@ -2037,8 +2070,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro |
|
|
|
unsigned int initial_timeout; |
|
|
|
unsigned int initial_timeout; |
|
|
|
double max, done; |
|
|
|
double max, done; |
|
|
|
int bufleft, err, got, tot; |
|
|
|
int bufleft, err, got, tot; |
|
|
|
__maybe_unused bool first = true; |
|
|
|
bool first = true; |
|
|
|
unsigned char *search; |
|
|
|
char *search; |
|
|
|
int endlen; |
|
|
|
int endlen; |
|
|
|
|
|
|
|
|
|
|
|
// We add 4: 1 for null, 2 for FTDI status and 1 to round to 4 bytes
|
|
|
|
// We add 4: 1 for null, 2 for FTDI status and 1 to round to 4 bytes
|
|
|
@ -2064,19 +2097,34 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro |
|
|
|
timeout = usbdev->found->timeout; |
|
|
|
timeout = usbdev->found->timeout; |
|
|
|
|
|
|
|
|
|
|
|
if (end == NULL) { |
|
|
|
if (end == NULL) { |
|
|
|
|
|
|
|
if (usbdev->buffer && usbdev->bufamt) { |
|
|
|
|
|
|
|
tot = usbdev->bufamt; |
|
|
|
|
|
|
|
bufleft = bufsiz - tot; |
|
|
|
|
|
|
|
memcpy(usbbuf, usbdev->buffer, tot); |
|
|
|
|
|
|
|
ptr = usbbuf + tot; |
|
|
|
|
|
|
|
usbdev->bufamt = 0; |
|
|
|
|
|
|
|
} else { |
|
|
|
tot = 0; |
|
|
|
tot = 0; |
|
|
|
ptr = usbbuf; |
|
|
|
|
|
|
|
bufleft = bufsiz; |
|
|
|
bufleft = bufsiz; |
|
|
|
|
|
|
|
ptr = usbbuf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = LIBUSB_SUCCESS; |
|
|
|
err = LIBUSB_SUCCESS; |
|
|
|
initial_timeout = timeout; |
|
|
|
initial_timeout = timeout; |
|
|
|
max = ((double)timeout) / 1000.0; |
|
|
|
max = ((double)timeout) / 1000.0; |
|
|
|
cgtime(&read_start); |
|
|
|
cgtime(&read_start); |
|
|
|
while (bufleft > 0) { |
|
|
|
while (bufleft > 0) { |
|
|
|
|
|
|
|
// TODO: use (USB_MAX_READ - tot) always?
|
|
|
|
|
|
|
|
if (usbdev->buffer) |
|
|
|
|
|
|
|
usbbufread = USB_MAX_READ - tot; |
|
|
|
|
|
|
|
else { |
|
|
|
if (ftdi) |
|
|
|
if (ftdi) |
|
|
|
usbbufread = bufleft + 2; |
|
|
|
usbbufread = bufleft + 2; |
|
|
|
else |
|
|
|
else |
|
|
|
usbbufread = bufleft; |
|
|
|
usbbufread = bufleft; |
|
|
|
|
|
|
|
} |
|
|
|
got = 0; |
|
|
|
got = 0; |
|
|
|
|
|
|
|
|
|
|
|
STATS_TIMEVAL(&tv_start); |
|
|
|
STATS_TIMEVAL(&tv_start); |
|
|
|
err = libusb_bulk_transfer(usbdev->handle, |
|
|
|
err = libusb_bulk_transfer(usbdev->handle, |
|
|
|
usbdev->found->eps[ep].ep, |
|
|
|
usbdev->found->eps[ep].ep, |
|
|
@ -2120,6 +2168,16 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// N.B. usbdev->buffer was emptied before the while() loop
|
|
|
|
|
|
|
|
if (usbdev->buffer && tot > (int)bufsiz) { |
|
|
|
|
|
|
|
usbdev->bufamt = tot - bufsiz; |
|
|
|
|
|
|
|
memcpy(usbdev->buffer, ptr + bufsiz, usbdev->bufamt); |
|
|
|
|
|
|
|
tot -= usbdev->bufamt; |
|
|
|
|
|
|
|
usbbuf[tot] = '\0'; |
|
|
|
|
|
|
|
applog(LOG_ERR, "USB: %s%i read1 buffering %d extra bytes", |
|
|
|
|
|
|
|
cgpu->drv->name, cgpu->device_id, usbdev->bufamt); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*processed = tot; |
|
|
|
*processed = tot; |
|
|
|
memcpy((char *)buf, (const char *)usbbuf, (tot < (int)bufsiz) ? tot + 1 : (int)bufsiz); |
|
|
|
memcpy((char *)buf, (const char *)usbbuf, (tot < (int)bufsiz) ? tot + 1 : (int)bufsiz); |
|
|
|
|
|
|
|
|
|
|
@ -2129,19 +2187,33 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro |
|
|
|
return err; |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (usbdev->buffer && usbdev->bufamt) { |
|
|
|
|
|
|
|
tot = usbdev->bufamt; |
|
|
|
|
|
|
|
bufleft = bufsiz - tot; |
|
|
|
|
|
|
|
memcpy(usbbuf, usbdev->buffer, tot); |
|
|
|
|
|
|
|
ptr = usbbuf + tot; |
|
|
|
|
|
|
|
usbdev->bufamt = 0; |
|
|
|
|
|
|
|
} else { |
|
|
|
tot = 0; |
|
|
|
tot = 0; |
|
|
|
ptr = usbbuf; |
|
|
|
|
|
|
|
bufleft = bufsiz; |
|
|
|
bufleft = bufsiz; |
|
|
|
|
|
|
|
ptr = usbbuf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
endlen = strlen(end); |
|
|
|
endlen = strlen(end); |
|
|
|
err = LIBUSB_SUCCESS; |
|
|
|
err = LIBUSB_SUCCESS; |
|
|
|
initial_timeout = timeout; |
|
|
|
initial_timeout = timeout; |
|
|
|
max = ((double)timeout) / 1000.0; |
|
|
|
max = ((double)timeout) / 1000.0; |
|
|
|
cgtime(&read_start); |
|
|
|
cgtime(&read_start); |
|
|
|
while (bufleft > 0) { |
|
|
|
while (bufleft > 0) { |
|
|
|
|
|
|
|
// TODO: use (USB_MAX_READ - tot) always?
|
|
|
|
|
|
|
|
if (usbdev->buffer) |
|
|
|
|
|
|
|
usbbufread = USB_MAX_READ - tot; |
|
|
|
|
|
|
|
else { |
|
|
|
if (ftdi) |
|
|
|
if (ftdi) |
|
|
|
usbbufread = bufleft + 2; |
|
|
|
usbbufread = bufleft + 2; |
|
|
|
else |
|
|
|
else |
|
|
|
usbbufread = bufleft; |
|
|
|
usbbufread = bufleft; |
|
|
|
|
|
|
|
} |
|
|
|
got = 0; |
|
|
|
got = 0; |
|
|
|
STATS_TIMEVAL(&tv_start); |
|
|
|
STATS_TIMEVAL(&tv_start); |
|
|
|
err = libusb_bulk_transfer(usbdev->handle, |
|
|
|
err = libusb_bulk_transfer(usbdev->handle, |
|
|
@ -2172,23 +2244,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro |
|
|
|
if (err || readonce) |
|
|
|
if (err || readonce) |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// WARNING - this will return data past END ('if' there is extra data)
|
|
|
|
if (find_end(usbbuf, ptr, got, tot, (char *)end, endlen, first)) |
|
|
|
if (endlen <= tot) { |
|
|
|
|
|
|
|
// If END is only 1 char - do a faster search
|
|
|
|
|
|
|
|
if (endlen == 1) { |
|
|
|
|
|
|
|
if (strchr((char *)ptr, *end)) |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} else { |
|
|
|
|
|
|
|
// must allow END to have been chopped in 2 transfers
|
|
|
|
|
|
|
|
if ((tot - got) >= (endlen - 1)) |
|
|
|
|
|
|
|
search = ptr - (endlen - 1); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
search = ptr - (tot - got); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strstr((char *)search, end)) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ptr += got; |
|
|
|
ptr += got; |
|
|
|
bufleft -= got; |
|
|
|
bufleft -= got; |
|
|
@ -2204,6 +2261,38 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (usbdev->buffer) { |
|
|
|
|
|
|
|
bool dobuffer = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((search = find_end(usbbuf, usbbuf, tot, tot, (char *)end, endlen, true))) { |
|
|
|
|
|
|
|
// end finishes after bufsiz
|
|
|
|
|
|
|
|
if ((search + endlen - (char *)usbbuf) > (int)bufsiz) { |
|
|
|
|
|
|
|
usbdev->bufamt = tot - bufsiz; |
|
|
|
|
|
|
|
dobuffer = true; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// extra data after end
|
|
|
|
|
|
|
|
if (*(search + endlen)) { |
|
|
|
|
|
|
|
usbdev->bufamt = tot - (search + endlen - (char *)usbbuf); |
|
|
|
|
|
|
|
dobuffer = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// no end, but still bigger than bufsiz
|
|
|
|
|
|
|
|
if (tot > (int)bufsiz) { |
|
|
|
|
|
|
|
usbdev->bufamt = tot - bufsiz; |
|
|
|
|
|
|
|
dobuffer = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dobuffer) { |
|
|
|
|
|
|
|
tot -= usbdev->bufamt; |
|
|
|
|
|
|
|
memcpy(usbdev->buffer, usbbuf + tot, usbdev->bufamt); |
|
|
|
|
|
|
|
usbbuf[tot] = '\0'; |
|
|
|
|
|
|
|
applog(LOG_ERR, "USB: %s%i read2 buffering %d extra bytes", |
|
|
|
|
|
|
|
cgpu->drv->name, cgpu->device_id, usbdev->bufamt); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*processed = tot; |
|
|
|
*processed = tot; |
|
|
|
memcpy((char *)buf, (const char *)usbbuf, (tot < (int)bufsiz) ? tot + 1 : (int)bufsiz); |
|
|
|
memcpy((char *)buf, (const char *)usbbuf, (tot < (int)bufsiz) ? tot + 1 : (int)bufsiz); |
|
|
|
|
|
|
|
|
|
|
@ -2400,6 +2489,45 @@ int usb_ftdi_cts(struct cgpu_info *cgpu) |
|
|
|
return (ret & FTDI_RS0_CTS); |
|
|
|
return (ret & FTDI_RS0_CTS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void usb_buffer_enable(struct cgpu_info *cgpu) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct cg_usb_device *cgusb = cgpu->usbdev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!cgusb->buffer) { |
|
|
|
|
|
|
|
cgusb->bufamt = 0; |
|
|
|
|
|
|
|
cgusb->buffer = malloc(USB_MAX_READ+1); |
|
|
|
|
|
|
|
if (!cgusb->buffer) |
|
|
|
|
|
|
|
quit(1, "Failed to malloc buffer for USB %s%i", |
|
|
|
|
|
|
|
cgpu->drv->name, cgpu->device_id); |
|
|
|
|
|
|
|
cgusb->bufsiz = USB_MAX_READ; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void usb_buffer_disable(struct cgpu_info *cgpu) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct cg_usb_device *cgusb = cgpu->usbdev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cgusb->buffer) { |
|
|
|
|
|
|
|
cgusb->bufamt = 0; |
|
|
|
|
|
|
|
cgusb->bufsiz = 0; |
|
|
|
|
|
|
|
free(cgusb->buffer); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void usb_buffer_clear(struct cgpu_info *cgpu) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct cg_usb_device *cgusb = cgpu->usbdev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cgusb->bufamt = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t usb_buffer_size(struct cgpu_info *cgpu) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct cg_usb_device *cgusb = cgpu->usbdev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return cgusb->bufamt; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void usb_cleanup() |
|
|
|
void usb_cleanup() |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cgpu_info *cgpu; |
|
|
|
struct cgpu_info *cgpu; |
|
|
|