Browse Source

Merge branch 'erupter' into bfgminer

Luke Dashjr 12 years ago
parent
commit
65ba3a196f
10 changed files with 242 additions and 11 deletions
  1. 1 0
      Makefile.am
  2. 5 0
      deviceapi.c
  3. 0 2
      driver-cairnsmore.c
  4. 84 0
      driver-erupter.c
  5. 120 9
      fpgautils.c
  6. 9 0
      fpgautils.h
  7. 2 0
      icarus-common.h
  8. 11 0
      miner.c
  9. 3 0
      miner.h
  10. 7 0
      util.h

+ 1 - 0
Makefile.am

@@ -179,6 +179,7 @@ endif
 if HAS_ICARUS
 bfgminer_SOURCES += driver-icarus.c icarus-common.h
 bfgminer_SOURCES += driver-cairnsmore.c
+bfgminer_SOURCES += driver-erupter.c
 endif
 
 if HAS_AVALON

+ 5 - 0
deviceapi.c

@@ -26,6 +26,7 @@
 
 #include "compat.h"
 #include "deviceapi.h"
+#include "fpgautils.h"
 #include "logging.h"
 #include "miner.h"
 #include "util.h"
@@ -617,6 +618,10 @@ bool add_cgpu(struct cgpu_info *cgpu)
 	strcpy(cgpu->proc_repr, cgpu->dev_repr);
 	sprintf(cgpu->proc_repr_ns, "%s%u", cgpu->drv->name, cgpu->device_id);
 	
+	cgpu->dev_manufacturer = maybe_strdup(detectone_meta_info.manufacturer);
+	cgpu->dev_product = maybe_strdup(detectone_meta_info.product);
+	cgpu->dev_serial = maybe_strdup(detectone_meta_info.serial);
+	
 	devices_new = realloc(devices_new, sizeof(struct cgpu_info *) * (total_devices_new + lpcount + 1));
 	devices_new[total_devices_new++] = cgpu;
 	

+ 0 - 2
driver-cairnsmore.c

@@ -196,8 +196,6 @@ static bool cairnsmore_identify(struct cgpu_info *cm1)
 	return true;
 }
 
-extern struct device_drv icarus_drv;
-
 static void cairnsmore_drv_init()
 {
 	cairnsmore_drv = icarus_drv;

+ 84 - 0
driver-erupter.c

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2013 Luke Dashjr
+ *
+ * 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
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#include "fpgautils.h"
+#include "icarus-common.h"
+
+#define ERUPTER_IO_SPEED 1500000
+#define ERUPTER_HASH_TIME 0.0000000029761
+
+extern struct device_drv erupter_drv;
+extern struct device_drv erupter_drv_emerald;
+
+static bool _erupter_detect_one(const char *devpath, struct device_drv *drv)
+{
+	struct ICARUS_INFO *info = calloc(1, sizeof(struct ICARUS_INFO));
+	if (unlikely(!info))
+		quit(1, "Failed to malloc ICARUS_INFO");
+
+	*info = (struct ICARUS_INFO){
+		.baud = ERUPTER_IO_SPEED,
+		.Hs = ERUPTER_HASH_TIME,
+		.timing_mode = MODE_DEFAULT,
+	};
+
+	if (!icarus_detect_custom(devpath, drv, info)) {
+		free(info);
+		return false;
+	}
+	return true;
+}
+
+static bool erupter_emerald_detect_one(const char *devpath)
+{
+	return _erupter_detect_one(devpath, &erupter_drv_emerald);
+}
+
+static bool erupter_detect_one(const char *devpath)
+{
+	return _erupter_detect_one(devpath, &erupter_drv);
+}
+
+static int erupter_emerald_detect_auto(void)
+{
+	return serial_autodetect(erupter_emerald_detect_one, "Block", "Erupter", "Emerald");
+}
+
+static int erupter_detect_auto(void)
+{
+	return serial_autodetect(erupter_detect_one, "Block", "Erupter");
+}
+
+static void erupter_drv_init();
+
+static void erupter_detect()
+{
+	erupter_drv_init();
+	// Actual serial detection is handled by Icarus driver
+	serial_detect_auto_byname(&erupter_drv_emerald, erupter_emerald_detect_one, erupter_emerald_detect_auto);
+	serial_detect_auto_byname(&erupter_drv, erupter_detect_one, erupter_detect_auto);
+}
+
+static void erupter_drv_init()
+{
+	erupter_drv = icarus_drv;
+	erupter_drv.dname = "erupter";
+	erupter_drv.name = "BES";
+	erupter_drv.drv_detect = erupter_detect;
+	
+	erupter_drv_emerald = erupter_drv;
+	erupter_drv_emerald.name = "BEE";
+}
+
+struct device_drv erupter_drv = {
+	// Needed to get to erupter_drv_init at all
+	.drv_detect = erupter_detect,
+};
+
+struct device_drv erupter_drv_emerald;

+ 120 - 9
fpgautils.c

@@ -16,6 +16,7 @@
 #include <winsock2.h>
 #endif
 
+#include <ctype.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -112,7 +113,50 @@ int _detectone_wrap(const detectone_func_t detectone, const char * const param,
 }
 #define detectone(param)  _detectone_wrap(detectone, param, __func__)
 
+struct detectone_meta_info_t detectone_meta_info;
+
+static
+void clear_detectone_meta_info(void)
+{
+	detectone_meta_info = (struct detectone_meta_info_t){
+		.manufacturer = NULL,
+	};
+}
+
 #ifdef HAVE_LIBUDEV
+static
+void _decode_udev_enc(char *o, const char *s)
+{
+	while(s[0])
+	{
+		if (s[0] == '\\' && s[1] == 'x' && s[2] && s[3])
+		{
+			hex2bin((void*)(o++), &s[2], 1);
+			s += 4;
+		}
+		else
+			(o++)[0] = (s++)[0];
+	}
+	o[0] = '\0';
+}
+
+static
+char *_decode_udev_enc_dup(const char *s)
+{
+	if (!s)
+		return NULL;
+	
+	char *o = malloc(strlen(s));
+	if (!o)
+	{
+		applog(LOG_ERR, "Failed to malloc in _decode_udev_enc_dup");
+		return NULL;
+	}
+	
+	_decode_udev_enc(o, s);
+	return o;
+}
+
 static
 int _serial_autodetect_udev(detectone_func_t detectone, va_list needles)
 {
@@ -138,14 +182,24 @@ int _serial_autodetect_udev(detectone_func_t detectone, va_list needles)
 			continue;
 		}
 
+		detectone_meta_info = (struct detectone_meta_info_t){
+			.manufacturer = _decode_udev_enc_dup(udev_device_get_property_value(device, "ID_VENDOR_ENC")),
+			.product = _decode_udev_enc_dup(udev_device_get_property_value(device, "ID_MODEL_ENC")),
+			.serial = _decode_udev_enc_dup(udev_device_get_property_value(device, "ID_SERIAL_SHORT")),
+		};
+		
 		const char *devpath = udev_device_get_devnode(device);
 		if (devpath && detectone(devpath))
 			++found;
 
+		free((void*)detectone_meta_info.manufacturer);
+		free((void*)detectone_meta_info.product);
+		free((void*)detectone_meta_info.serial);
 		udev_device_unref(device);
 	}
 	udev_enumerate_unref(enumerate);
 	udev_unref(udev);
+	clear_detectone_meta_info();
 
 	return found;
 }
@@ -164,6 +218,9 @@ int _serial_autodetect_devserial(detectone_func_t detectone, va_list needles)
 	char *devfile = devpath + sizeof(udevdir);
 	char found = 0;
 
+	// No way to split this out of the filename reliably
+	clear_detectone_meta_info();
+	
 	D = opendir(udevdir);
 	if (!D)
 		return 0;
@@ -186,16 +243,40 @@ int _serial_autodetect_devserial(detectone_func_t detectone, va_list needles)
 #endif
 
 #ifndef WIN32
+static
+char *_sysfs_do_read(char *buf, size_t bufsz, const char *devpath, char *devfile, const char *append)
+{
+	FILE *F;
+	
+	strcpy(devfile, append);
+	F = fopen(devpath, "r");
+	if (F)
+	{
+		if (fgets(buf, bufsz, F))
+		{
+			size_t L = strlen(buf);
+			while (isspace(buf[--L]))
+				buf[L] = '\0';
+		}
+		else
+			buf[0] = '\0';
+		fclose(F);
+	}
+	else
+		buf[0] = '\0';
+	
+	return buf[0] ? buf : NULL;
+}
+
 static
 int _serial_autodetect_sysfs(detectone_func_t detectone, va_list needles)
 {
 	DIR *D, *DS, *DT;
-	FILE *F;
 	struct dirent *de;
 	const char devroot[] = "/sys/bus/usb/devices";
 	const size_t devrootlen = sizeof(devroot) - 1;
 	char devpath[sizeof(devroot) + (NAME_MAX * 3)];
-	char buf[0x100];
+	char ttybuf[0x10], manuf[0x40], prod[0x40], serial[0x40];
 	char *devfile, *upfile;
 	char found = 0;
 	size_t len, len2;
@@ -211,12 +292,11 @@ int _serial_autodetect_sysfs(detectone_func_t detectone, va_list needles)
 		upfile = &devpath[devrootlen + 1];
 		memcpy(upfile, de->d_name, len);
 		devfile = upfile + len;
-		strcpy(devfile, "/product");
-		F = fopen(devpath, "r");
-		if (!(F && fgets(buf, sizeof(buf), F)))
+		
+		if (!_sysfs_do_read(prod, sizeof(prod), devpath, devfile, "/product"))
 			continue;
 		
-		if (!SEARCH_NEEDLES(buf))
+		if (!SEARCH_NEEDLES(prod))
 			continue;
 		
 		devfile[0] = '\0';
@@ -226,7 +306,7 @@ int _serial_autodetect_sysfs(detectone_func_t detectone, va_list needles)
 		devfile[0] = '/';
 		++devfile;
 		
-		memcpy(buf, "/dev/", 5);
+		memcpy(ttybuf, "/dev/", 5);
 		
 		while ( (de = readdir(DS)) )
 		{
@@ -247,8 +327,15 @@ int _serial_autodetect_sysfs(detectone_func_t detectone, va_list needles)
 				if (strncmp(&de->d_name[3], "USB", 3) && strncmp(&de->d_name[3], "ACM", 3))
 					continue;
 				
-				strcpy(&buf[5], de->d_name);
-				if (detectone(buf))
+				
+				detectone_meta_info = (struct detectone_meta_info_t){
+					.manufacturer = _sysfs_do_read(manuf, sizeof(manuf), devpath, devfile, "/manufacturer"),
+					.product = prod,
+					.serial = _sysfs_do_read(serial, sizeof(serial), devpath, devfile, "/serial"),
+				};
+				
+				strcpy(&ttybuf[5], de->d_name);
+				if (detectone(ttybuf))
 					++found;
 			}
 			closedir(DT);
@@ -256,6 +343,7 @@ int _serial_autodetect_sysfs(detectone_func_t detectone, va_list needles)
 		closedir(DS);
 	}
 	closedir(D);
+	clear_detectone_meta_info();
 	
 	return found;
 }
@@ -271,6 +359,16 @@ int _serial_autodetect_sysfs(detectone_func_t detectone, va_list needles)
 	}  \
 } while(0)
 
+#ifdef UNTESTED_FTDI_DETECTONE_META_INFO
+static
+char *_ftdi_get_string(char *buf, int i, DWORD flags)
+{
+	if (FT_OK != FT_ListDevices((PVOID)i, buf, FT_LIST_BY_INDEX | flags))
+		return NULL;
+	return buf[0] ? buf : NULL;
+}
+#endif
+
 static
 int _serial_autodetect_ftdi(detectone_func_t detectone, va_list needles)
 {
@@ -278,6 +376,9 @@ int _serial_autodetect_ftdi(detectone_func_t detectone, va_list needles)
 	char *devpathnum = &devpath[7];
 	char **bufptrs;
 	char *buf;
+#ifdef UNTESTED_FTDI_DETECTONE_META_INFO
+	char manuf[64], serial[64];
+#endif
 	int found = 0;
 	DWORD i;
 
@@ -312,6 +413,7 @@ int _serial_autodetect_ftdi(detectone_func_t detectone, va_list needles)
 		goto out;
 	}
 	
+	clear_detectone_meta_info();
 	for (i = numDevs; i > 0; ) {
 		--i;
 		bufptrs[i][64] = '\0';
@@ -329,6 +431,13 @@ int _serial_autodetect_ftdi(detectone_func_t detectone, va_list needles)
 			continue;
 		
 		applog(LOG_ERR, "FT_GetComPortNumber(%p (%ld), %ld)", ftHandle, (long)i, (long)lComPortNumber);
+#ifdef UNTESTED_FTDI_DETECTONE_META_INFO
+		detectone_meta_info = (struct detectone_meta_info_t){
+			.product = bufptrs[i],
+			.serial = _ftdi_get_string(serial, i, FT_OPEN_BY_SERIAL_NUMBER),
+		};
+#endif
+		
 		sprintf(devpathnum, "%d", (int)lComPortNumber);
 		
 		if (detectone(devpath))
@@ -336,6 +445,7 @@ int _serial_autodetect_ftdi(detectone_func_t detectone, va_list needles)
 	}
 
 out:
+	clear_detectone_meta_info();
 	dlclose(dll);
 	return found;
 }
@@ -372,6 +482,7 @@ int _serial_detect(struct device_drv *api, detectone_func_t detectone, autoscan_
 	size_t namel = strlen(api->name);
 	size_t dnamel = strlen(api->dname);
 
+	clear_detectone_meta_info();
 	DL_FOREACH_SAFE(scan_devices, iter, tmp) {
 		dev = iter->string;
 		if ((colon = strchr(dev, ':')) && colon[1] != '\0') {

+ 9 - 0
fpgautils.h

@@ -9,6 +9,15 @@
 struct device_drv;
 struct cgpu_info;
 
+struct detectone_meta_info_t {
+	const char *manufacturer;
+	const char *product;
+	const char *serial;
+};
+
+// NOTE: Should detectone become run multithreaded, this will become a threadsafe #define
+extern struct detectone_meta_info_t detectone_meta_info;
+
 typedef bool(*detectone_func_t)(const char*);
 typedef int(*autoscan_func_t)();
 

+ 2 - 0
icarus-common.h

@@ -35,6 +35,8 @@
 // keeping a ongoing average of recent data
 #define INFO_HISTORY 10
 
+extern struct device_drv icarus_drv;
+
 struct ICARUS_HISTORY {
 	struct timeval finish;
 	double sumXiTi;

+ 11 - 0
miner.c

@@ -6018,6 +6018,15 @@ refresh:
 	wattroff(logwin, A_BOLD);
 	wlogprint("\n");
 	
+	if (cgpu->dev_manufacturer)
+		wlogprint("  %s from %s\n", (cgpu->dev_product ?: "Device"), cgpu->dev_manufacturer);
+	else
+	if (cgpu->dev_product)
+		wlogprint("  %s\n", cgpu->dev_product);
+	
+	if (cgpu->dev_serial)
+		wlogprint("Serial: %s\n", cgpu->dev_serial);
+	
 	if (drv->proc_wlogprint_status && likely(cgpu->status != LIFE_INIT))
 		drv->proc_wlogprint_status(cgpu);
 	
@@ -8656,6 +8665,7 @@ extern struct device_drv bitforce_drv;
 
 #ifdef USE_ICARUS
 extern struct device_drv cairnsmore_drv;
+extern struct device_drv erupter_drv;
 extern struct device_drv icarus_drv;
 #endif
 
@@ -8754,6 +8764,7 @@ void drv_detect_all()
 	if (!opt_scrypt)
 	{
 		cairnsmore_drv.drv_detect();
+		erupter_drv.drv_detect();
 		icarus_drv.drv_detect();
 	}
 #endif

+ 3 - 0
miner.h

@@ -446,6 +446,9 @@ struct cgpu_info {
 	
 	const char *device_path;
 	void *device_data;
+	char *dev_manufacturer;
+	char *dev_product;
+	char *dev_serial;
 	union {
 #ifdef USE_ZTEX
 		struct libztex_device *device_ztex;

+ 7 - 0
util.h

@@ -197,4 +197,11 @@ struct timeval *select_timeout(struct timeval *tvp_timeout, struct timeval *tvp_
 } while(0)
 
 
+static inline
+char *maybe_strdup(const char *s)
+{
+	return s ? strdup(s) : NULL;
+}
+
+
 #endif /* __UTIL_H__ */