Example #1
0
int
main(int argc, char **argv)
{
	uint32_t time;

	usb_init();

	time = 0;

	while (1) {

		usb_idle();

		usleep(1000);

		if (++time >= (1000 / hz)) {
			time = 0;
			callout_process(1);
		}
	}

	usb_uninit();

	return (0);
}
Example #2
0
static struct cgpu_info *hfa_detect_one(libusb_device *dev, struct usb_find_devices *found)
{
    struct cgpu_info *hashfast;

    hashfast = usb_alloc_cgpu(&hashfast_drv, HASHFAST_MINER_THREADS);
    if (!hashfast)
        quit(1, "Failed to usb_alloc_cgpu hashfast");

    if (!usb_init(hashfast, dev, found)) {
        hashfast = usb_free_cgpu(hashfast);
        return NULL;
    }

    hashfast->usbdev->usb_type = USB_TYPE_STD;

    if (!hfa_initialise(hashfast)) {
        hashfast = usb_free_cgpu(hashfast);
        return NULL;
    }
    if (opt_hfa_dfu_boot) {
        hfa_dfu_boot(hashfast);
        hashfast = usb_free_cgpu(hashfast);
        return NULL;
    }
    if (!hfa_detect_common(hashfast)) {
        usb_uninit(hashfast);
        hashfast = usb_free_cgpu(hashfast);
        return NULL;
    }
    if (!add_cgpu(hashfast))
        return NULL;

    return hashfast;
}
Example #3
0
static bool klondike_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
	struct cgpu_info *klninfo = calloc(1, sizeof(*klninfo));
	char replybuf[REPLY_BUFSIZE];
	char devpath[20];
	int attempts = 0;
	int sent, recd, err;

	if (unlikely(!klninfo))
		quit(1, "Failed to calloc klninfo in klondike_detect_one");
		
	klninfo->drv = &klondike_drv;
	klninfo->deven = DEV_ENABLED;
	klninfo->threads = 1;
	
	if (usb_init(klninfo, dev, found)) {
		
		sprintf(devpath, "%d:%d", (int)(klninfo->usbinfo.bus_number), (int)(klninfo->usbinfo.device_address));
		while(attempts++ < 2) {
			
			err = usb_write(klninfo, "I", 2, &sent, C_REQUESTIDENTIFY);
			if (err < 0 || sent != 2) {
				applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", klninfo->drv->dname, devpath, sent, err);
				break;
			}
				
			err = usb_read(klninfo, replybuf, sizeof(replybuf), &recd, C_GETIDENTIFY);
			if (err < 0) {
				applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", klninfo->drv->dname, devpath, recd, err);
			} else if (recd < 1) {
				applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",	klninfo->drv->dname, devpath, recd);
			} else if (replybuf[0] == 'I' && replybuf[1] == 0) {
				applog(LOG_DEBUG, "%s (%s) identified as: '%s'", klninfo->drv->dname, devpath, klninfo->drv->name);
				
				// do something with id info
				
				update_usb_stats(klninfo);
				return true;
			}
		}
		usb_uninit(klninfo);
	}
	free(klninfo);
	return false;
}
Example #4
0
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
	char buf[BITFORCE_BUFSIZ+1];
	char devpath[20];
	int err, amount;
	char *s;

	struct cgpu_info *bitforce = NULL;
	bitforce = calloc(1, sizeof(*bitforce));
	bitforce->drv = &bitforce_drv;
	bitforce->deven = DEV_ENABLED;
	bitforce->threads = 1;

	if (!usb_init(bitforce, dev, found)) {
		applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)",
			bitforce->drv->dname,
			(int)libusb_get_bus_number(dev),
			(int)libusb_get_device_address(dev));
		goto shin;
	}

	sprintf(devpath, "%d:%d",
			(int)(bitforce->usbdev->bus_number),
			(int)(bitforce->usbdev->device_address));

	int init_count = 0;
reinit:

	bitforce_initialise(bitforce, false);

	if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) {
		applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)",
			bitforce->drv->dname, devpath, amount, err);
		goto unshin;
	}

	if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) {
		// Maybe it was still processing previous work?
		if (++init_count <= REINIT_COUNT) {
			if (init_count < 2) {
				applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)",
					bitforce->drv->dname, devpath, amount, err);
			}
			nmsleep(REINIT_TIME_MS);
			goto reinit;
		}

		if (init_count > 0)
			applog(LOG_WARNING, "%s detect (%s) init failed %d times",
				bitforce->drv->dname, devpath, init_count);

		if (err < 0) {
			applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)",
				bitforce->drv->dname, devpath, amount, err);
		} else {
			applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",
				bitforce->drv->dname, devpath, amount);
		}

		goto unshin;
	}
	buf[amount] = '\0';

	if (unlikely(!strstr(buf, "SHA256"))) {
		applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'",
			bitforce->drv->dname, devpath, buf);
		goto unshin;
	}

	if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) {
		s[0] = '\0';
		bitforce->name = strdup(buf + 7);
	} else {
		bitforce->name = (char *)blank;
	}

	// We have a real BitForce!
	applog(LOG_DEBUG, "%s (%s) identified as: '%s'",
		bitforce->drv->dname, devpath, bitforce->name);

	/* Initially enable support for nonce range and disable it later if it
	 * fails */
	if (opt_bfl_noncerange) {
		bitforce->nonce_range = true;
		bitforce->sleep_ms = BITFORCE_SLEEP_MS;
		bitforce->kname = KNAME_RANGE;
	} else {
		bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5;
		bitforce->kname = KNAME_WORK;
	}

	bitforce->device_path = strdup(devpath);

	if (!add_cgpu(bitforce))
		goto unshin;

	update_usb_stats(bitforce);

	mutex_init(&bitforce->device_mutex);

	return true;

unshin:

	usb_uninit(bitforce);

shin:

	free(bitforce->device_path);

	if (bitforce->name != blank)
		free(bitforce->name);

	free(bitforce);

	return false;
}
Example #5
0
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
	char buf[BITFORCE_BUFSIZ+1];
	int err, amount;
	char *s;
	struct timeval init_start, init_now;
	int init_sleep, init_count;
	bool ident_first;

	struct cgpu_info *bitforce = usb_alloc_cgpu(&bitforce_drv, 1);

	if (!usb_init(bitforce, dev, found))
		goto shin;

	// Allow 2 complete attempts if the 1st time returns an unrecognised reply
	ident_first = true;
retry:
	init_count = 0;
	init_sleep = REINIT_TIME_FIRST_MS;
	cgtime(&init_start);
reinit:
	bitforce_initialise(bitforce, false);
	if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) {
		applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)",
			bitforce->drv->dname, bitforce->device_path, amount, err);
		goto unshin;
	}

	if ((err = usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) {
		init_count++;
		cgtime(&init_now);
		if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) {
			if (init_count == 2) {
				applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying",
					bitforce->drv->dname, bitforce->device_path, amount, err);
			}
			nmsleep(init_sleep);
			if ((init_sleep * 2) <= REINIT_TIME_MAX_MS)
				init_sleep *= 2;
			goto reinit;
		}

		if (init_count > 0)
			applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs",
				bitforce->drv->dname, bitforce->device_path, init_count, tdiff(&init_now, &init_start));

		if (err < 0) {
			applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)",
				bitforce->drv->dname, bitforce->device_path, amount, err);
		} else {
			applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",
				bitforce->drv->dname, bitforce->device_path, amount);
		}

		goto unshin;
	}
	buf[amount] = '\0';

	if (unlikely(!strstr(buf, "SHA256"))) {
		if (ident_first) {
			applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...",
				bitforce->drv->dname, bitforce->device_path, buf);
			ident_first = false;
			goto retry;
		}
		applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt",
			bitforce->drv->dname, bitforce->device_path, buf);
		goto unshin;
	}

	if (strstr(buf, "SHA256 SC")) {
#ifdef USE_BFLSC
		applog(LOG_DEBUG, "SC device detected, will defer to BFLSC driver");
#else
		applog(LOG_WARNING, "SC device detected but no BFLSC support compiled in!");
#endif
		goto unshin;
	}

	if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) {
		s[0] = '\0';
		bitforce->name = strdup(buf + 7);
	} else {
		bitforce->name = (char *)blank;
	}

	// We have a real BitForce!
	applog(LOG_DEBUG, "%s (%s) identified as: '%s'",
		bitforce->drv->dname, bitforce->device_path, bitforce->name);

	/* Initially enable support for nonce range and disable it later if it
	 * fails */
	if (opt_bfl_noncerange) {
		bitforce->nonce_range = true;
		bitforce->sleep_ms = BITFORCE_SLEEP_MS;
		bitforce->kname = KNAME_RANGE;
	} else {
		bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5;
		bitforce->kname = KNAME_WORK;
	}

	if (!add_cgpu(bitforce))
		goto unshin;

	update_usb_stats(bitforce);

	mutex_init(&bitforce->device_mutex);

	return true;

unshin:

	usb_uninit(bitforce);

shin:

	if (bitforce->name != blank) {
		free(bitforce->name);
		bitforce->name = NULL;
	}

	bitforce = usb_free_cgpu(bitforce);

	return false;
}
Example #6
0
static bool gridseed_detect_one(libusb_device *dev, struct usb_find_devices *found)
{
	struct cgpu_info *gridseed;
	GRIDSEED_INFO *info;
	int err, wrote, def_freq_inx;
	unsigned char rbuf[GRIDSEED_READ_SIZE];
#if 0
	const char detect_cmd[] =
		"55aa0f01"
		"4a548fe471fa3a9a1371144556c3f64d"
		"2500b4826008fe4bbf7698c94eba7946"
		"ce22a72f4f6726141a0b3287eeeeeeee";
	unsigned char detect_data[52];
#else
	const char detect_cmd[] = "55aac000909090900000000001000000";
	unsigned char detect_data[16];
#endif

	gridseed = usb_alloc_cgpu(&gridseed_drv, GRIDSEED_MINER_THREADS);
	if (!usb_init(gridseed, dev, found))
		goto shin;

	libusb_reset_device(gridseed->usbdev->handle);

	info = (GRIDSEED_INFO*)calloc(sizeof(GRIDSEED_INFO), 1);
	if (unlikely(!info))
		quit(1, "Failed to calloc gridseed_info data");
	gridseed->device_data = (void *)info;

	info->baud = GRIDSEED_DEFAULT_BAUD;
	info->freq = GRIDSEED_DEFAULT_FREQUENCY;
	def_freq_inx = gc3355_find_freq_index(GRIDSEED_DEFAULT_FREQUENCY);
	memcpy(info->freq_cmd, bin_frequency[def_freq_inx], 8);
	info->chips = GRIDSEED_DEFAULT_CHIPS;
	info->voltage = 0;
	info->per_chip_stats = 0;
	info->serial = strdup(gridseed->usbdev->serial_string);
	memset(info->nonce_count, 0, sizeof(info->nonce_count));
	memset(info->error_count, 0, sizeof(info->error_count));

	get_options(info, opt_gridseed_options);
	get_freq(info, opt_gridseed_freq);
	get_chips(info, opt_gridseed_chips);

	update_usb_stats(gridseed);

	gridseed->usbdev->usb_type = USB_TYPE_STD;
	gridseed_initialise(gridseed, info);

	/* get MCU firmware version */
	hex2bin(detect_data, detect_cmd, sizeof(detect_data));
	if (gc3355_write_data(gridseed, detect_data, sizeof(detect_data))) {
		applog(LOG_DEBUG, "Failed to write work data to %i, err %d",
			gridseed->device_id, err);
		goto unshin;
	}

	/* waiting for return */
	if (gc3355_get_data(gridseed, rbuf, GRIDSEED_READ_SIZE)) {
		applog(LOG_DEBUG, "No response from %i", gridseed->device_id);
		goto unshin;
	}

	if (memcmp(rbuf, "\x55\xaa\xc0\x00\x90\x90\x90\x90", GRIDSEED_READ_SIZE-4) != 0) {
		applog(LOG_DEBUG, "Bad response from %i",
			gridseed->device_id);
		goto unshin;
	}

	info->fw_version = le32toh(*(uint32_t *)(rbuf+8));
	applog(LOG_NOTICE, "Device found, firmware version %08X, driver version %s",
		info->fw_version, gridseed_version);

	gc3355_init(gridseed, info);

	gridseed->algorithm = default_algorithm;

	if (!add_cgpu(gridseed))
		goto unshin;

	return true;

unshin:
	usb_uninit(gridseed);
	free(gridseed->device_data);
	gridseed->device_data = NULL;

shin:
	gridseed = usb_free_cgpu(gridseed);
	return false;
}
Example #7
0
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
    char buf[BITFORCE_BUFSIZ+1];
    char devpath[20];
    int err, amount;
    char *s;
    struct timeval init_start, init_now;
    int init_sleep, init_count;
    bool ident_first;

    struct cgpu_info *bitforce = NULL;
    bitforce = calloc(1, sizeof(*bitforce));
    bitforce->drv = &bitforce_drv;
    bitforce->deven = DEV_ENABLED;
    bitforce->threads = 1;

    if (!usb_init(bitforce, dev, found)) {
        applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)",
               bitforce->drv->dname,
               (int)(bitforce->usbinfo.bus_number),
               (int)(bitforce->usbinfo.device_address));
        goto shin;
    }

    sprintf(devpath, "%d:%d",
            (int)(bitforce->usbinfo.bus_number),
            (int)(bitforce->usbinfo.device_address));


    // Allow 2 complete attempts if the 1st time returns an unrecognised reply
    ident_first = true;
retry:
    init_count = 0;
    init_sleep = REINIT_TIME_FIRST_MS;
    gettimeofday(&init_start, NULL);
reinit:
    bitforce_initialise(bitforce, false);
    if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) {
        applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)",
               bitforce->drv->dname, devpath, amount, err);
        goto unshin;
    }

    if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) {
        init_count++;
        gettimeofday(&init_now, NULL);
        if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) {
            if (init_count == 2) {
                applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying",
                       bitforce->drv->dname, devpath, amount, err);
            }
            nmsleep(init_sleep);
            if ((init_sleep * 2) <= REINIT_TIME_MAX_MS)
                init_sleep *= 2;
            goto reinit;
        }

        if (init_count > 0)
            applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs",
                   bitforce->drv->dname, devpath, init_count, tdiff(&init_now, &init_start));

        if (err < 0) {
            applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)",
                   bitforce->drv->dname, devpath, amount, err);
        } else {
            applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",
                   bitforce->drv->dname, devpath, amount);
        }

        goto unshin;
    }
    buf[amount] = '\0';

    if (unlikely(!strstr(buf, "SHA256"))) {
        if (ident_first) {
            applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...",
                   bitforce->drv->dname, devpath, buf);
            ident_first = false;
            goto retry;
        }
        applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt",
               bitforce->drv->dname, devpath, buf);
        goto unshin;
    }

    if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) {
        s[0] = '\0';
        bitforce->name = strdup(buf + 7);
    } else {
        bitforce->name = (char *)blank;
    }

    // We have a real BitForce!
    applog(LOG_DEBUG, "%s (%s) identified as: '%s'",
           bitforce->drv->dname, devpath, bitforce->name);

    /* Initially enable support for nonce range and disable it later if it
     * fails */
    if (opt_bfl_noncerange) {
        bitforce->nonce_range = true;
        bitforce->sleep_ms = BITFORCE_SLEEP_MS;
        bitforce->kname = KNAME_RANGE;
    } else {
        bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5;
        bitforce->kname = KNAME_WORK;
    }

    bitforce->device_path = strdup(devpath);

    if (!add_cgpu(bitforce))
        goto unshin;

    update_usb_stats(bitforce);

    mutex_init(&bitforce->device_mutex);

    return true;

unshin:

    usb_uninit(bitforce);

shin:

    free(bitforce->device_path);

    if (bitforce->name != blank)
        free(bitforce->name);

    if (bitforce->drv->copy)
        free(bitforce->drv);

    free(bitforce);

    return false;
}
Example #8
0
static struct cgpu_info *gridseed_detect_one(libusb_device *dev, struct usb_find_devices *found)
{
	struct cgpu_info *gridseed;
	GRIDSEED_INFO *info;
	int this_option_offset;
	int baud, freq, chips, modules, usefifo, btcore;
	int err, wrote;
	bool configured;
	unsigned char rbuf[GRIDSEED_READ_SIZE];
	unsigned char *p;
#if 0
	const char detect_cmd[] =
		"55aa0f01"
		"4a548fe471fa3a9a1371144556c3f64d"
		"2500b4826008fe4bbf7698c94eba7946"
		"ce22a72f4f6726141a0b3287eeeeeeee";
	unsigned char detect_data[52];
#else
	const char detect_cmd[] = "55aac000909090900000000001000000";
	unsigned char detect_data[16];
#endif

	gridseed = usb_alloc_cgpu(&gridseed_drv, GRIDSEED_MINER_THREADS);
	if (!usb_init(gridseed, dev, found))
		goto shin;

	libusb_reset_device(gridseed->usbdev->handle);

	baud = GRIDSEED_DEFAULT_BAUD;
	chips = GRIDSEED_DEFAULT_CHIPS;
	modules = GRIDSEED_DEFAULT_MODULES;
	freq = gc3355_find_freq_index(GRIDSEED_DEFAULT_FREQUENCY);
	usefifo = GRIDSEED_DEFAULT_USEFIFO;
	btcore = GRIDSEED_DEFAULT_BTCORE;

	this_option_offset = 0;
	configured = get_options(this_option_offset, gridseed, opt_gridseed_options,
		&baud, &freq, &chips, &modules, &usefifo, &btcore);

	info = (GRIDSEED_INFO*)calloc(sizeof(GRIDSEED_INFO), 1);
	if (unlikely(!info))
		quit(1, "Failed to calloc gridseed_info data");
	gridseed->device_data = (void *)info;

	update_usb_stats(gridseed);

	//if (configured) {
		info->baud = baud;
		info->freq = freq;
		info->chips = chips;
		info->modules = modules;
		info->usefifo = usefifo;
		info->btcore = btcore;
	//}

	gridseed->usbdev->usb_type = USB_TYPE_STD;
	gridseed_initialise(gridseed, info);

	/* send testing work to chips */
	hex2bin(detect_data, detect_cmd, sizeof(detect_data));
	if (gc3355_write_data(gridseed, detect_data, sizeof(detect_data))) {
		applog(LOG_DEBUG, "Failed to write work data to %i, err %d",
			gridseed->device_id, err);
		goto unshin;
	}

	/* waiting for return */
	if (gc3355_get_data(gridseed, rbuf, GRIDSEED_READ_SIZE)) {
		applog(LOG_DEBUG, "No response from %i",
			gridseed->device_id);
		goto unshin;
	}

	if (memcmp(rbuf, "\x55\xaa\xc0\x00\x90\x90\x90\x90", GRIDSEED_READ_SIZE-4) != 0) {
		applog(LOG_DEBUG, "Bad response from %i",
			gridseed->device_id);
		goto unshin;
	}

	p = bin2hex(rbuf+GRIDSEED_READ_SIZE-4, 4);
	applog(LOG_NOTICE, "Device found, firmware version 0x%s, driver version %s", p, gridseed_version);
	free(p);

	if (!add_cgpu(gridseed))
		goto unshin;

	return gridseed;

unshin:
	usb_uninit(gridseed);
	free(gridseed->device_data);
	gridseed->device_data = NULL;

shin:
	gridseed = usb_free_cgpu(gridseed);
	return NULL;
}
Example #9
0
static struct cgpu_info *hashratio_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
	struct hashratio_info *info;
	int err, amount;
	int ackdetect;
	char mm_version[16];

	struct cgpu_info *hashratio = usb_alloc_cgpu(&hashratio_drv, 1);
	struct hashratio_pkg detect_pkg;
	struct hashratio_ret ret_pkg;

	if (!usb_init(hashratio, dev, found)) {
		applog(LOG_ERR, "Hashratio failed usb_init");
		hashratio = usb_free_cgpu(hashratio);
		return NULL;
	}

	hashratio_initialise(hashratio);

	strcpy(mm_version, "NONE");
	/* Send out detect pkg */
	memset(detect_pkg.data, 0, HRTO_P_DATA_LEN);

	hashratio_init_pkg(&detect_pkg, HRTO_P_DETECT, 1, 1);
	hashratio_send_pkg(hashratio, &detect_pkg);
	err = usb_read(hashratio, (char *)&ret_pkg, HRTO_READ_SIZE, &amount, C_HRO_READ);
	if (err || amount != HRTO_READ_SIZE) {
		applog(LOG_ERR, "%s %d: Hashratio failed usb_read with err %d amount %d",
		       hashratio->drv->name, hashratio->device_id, err, amount);
		usb_uninit(hashratio);
		usb_free_cgpu(hashratio);
		return NULL;
	}

	ackdetect = ret_pkg.type;
	applog(LOG_DEBUG, "hashratio Detect ID: %d", ackdetect);
	
	if (ackdetect != HRTO_P_ACKDETECT) {
		applog(LOG_DEBUG, "Not a hashratio device");
		usb_uninit(hashratio);
		usb_free_cgpu(hashratio);
		return NULL;
	}

	memcpy(mm_version, ret_pkg.data, 15);
	mm_version[15] = '\0';

	/* We have a real Hashratio! */
	hashratio->threads = HRTO_MINER_THREADS;
	add_cgpu(hashratio);

	update_usb_stats(hashratio);

	applog(LOG_INFO, "%s%d: Found at %s", hashratio->drv->name, hashratio->device_id,
	       hashratio->device_path);

	hashratio->device_data = cgcalloc(sizeof(struct hashratio_info), 1);

	info = hashratio->device_data;

	strcpy(info->mm_version, mm_version);

	info->fan_pwm  = HRTO_DEFAULT_FAN / 100 * HRTO_PWM_MAX;
	info->temp_max = 0;
	info->temp_history_index = 0;
	info->temp_sum = 0;
	info->temp_old = 0;
	info->default_freq = hashratio_freq;

	return hashratio;
}