Browse Source

Split a hid lowlevel out of mcp2210

Luke Dashjr 12 years ago
parent
commit
cd2b7906b4
8 changed files with 249 additions and 145 deletions
  1. 5 1
      Makefile.am
  2. 8 1
      configure.ac
  3. 3 2
      driver-nanofury.c
  4. 189 0
      lowl-hid.c
  5. 25 0
      lowl-hid.h
  6. 5 0
      lowlevel.c
  7. 3 0
      lowlevel.h
  8. 11 141
      mcp2210.c

+ 5 - 1
Makefile.am

@@ -257,10 +257,14 @@ endif
 
 if HAS_NANOFURY
 bfgminer_SOURCES += driver-nanofury.c mcp2210.c mcp2210.h
-bfgminer_CPPFLAGS += $(hidapi_CFLAGS)
 endif
 endif
 
+if NEED_BFG_LOWL_HID
+bfgminer_SOURCES += lowl-hid.c lowl-hid.h
+bfgminer_CPPFLAGS += $(hidapi_CFLAGS)
+endif
+
 bin_PROGRAMS += bfgminer-rpc
 bfgminer_rpc_SOURCES = api-example.c
 bfgminer_rpc_LDADD = @WS2_LIBS@

+ 8 - 1
configure.ac

@@ -112,6 +112,7 @@ optlist=
 need_dynclock=no
 need_fpgautils=no
 need_lowlevel=no
+need_lowl_hid=no
 have_cygwin=false
 have_win32=false
 have_macho=false
@@ -658,7 +659,6 @@ elif test "x$bitfury" = "xyes"; then
 	fi
 elif test "x$nanofury" = "xyes"; then
 	AC_MSG_ERROR([You explicitly disabled Bitfury and explicitly enabled NanoFury])
-	need_fpgautils=yes
 else
 	nanofury=no
 fi
@@ -666,6 +666,7 @@ if test "x$nanofury" = "xyes"; then
 	AC_DEFINE([USE_NANOFURY], [1], [Defined to 1 if NanoFury support is wanted])
 	need_fpgautils=yes
 	need_lowlevel=yes
+	need_lowl_hid=yes
 fi
 AM_CONDITIONAL([HAS_NANOFURY], [test x$nanofury = xyes])
 
@@ -753,6 +754,11 @@ if test x$need_fpgautils = xyes; then
 	fi
 fi
 
+if test x$need_lowl_hid = xyes; then
+	AC_DEFINE([NEED_BFG_LOWL_HID], [1], [Defined to 1 if lowlevel hid drivers are being used])
+	need_lowlevel=yes
+fi
+
 if test x$need_lowlevel = xyes; then
 	AC_DEFINE([HAVE_BFG_LOWLEVEL], [1], [Defined to 1 if lowlevel drivers are being used])
 fi
@@ -910,6 +916,7 @@ AC_SUBST(libblkmaker_LIBS)
 AM_CONDITIONAL([NEED_LIBBLKMAKER], [test x$with_system_libblkmaker != xyes])
 AM_CONDITIONAL([NEED_DYNCLOCK], [test x$need_dynclock = xyes])
 AM_CONDITIONAL([NEED_FPGAUTILS], [test x$need_fpgautils = xyes])
+AM_CONDITIONAL([NEED_BFG_LOWL_HID], [test x$need_lowl_hid = xyes])
 AM_CONDITIONAL([NEED_BFG_LOWLEVEL], [test x$need_lowlevel = xyes])
 AM_CONDITIONAL([HAS_SCRYPT], [test x$scrypt = xyes])
 AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes])

+ 3 - 2
driver-nanofury.c

@@ -169,8 +169,9 @@ bool nanofury_foundlowl(struct lowlevel_device_info * const info, __maybe_unused
 	
 	if (info->lowl != &lowl_mcp2210)
 	{
-		applog(LOG_WARNING, "%s: Matched \"%s\" serial \"%s\", but lowlevel driver is not mcp2210!",
-		       __func__, product, serial);
+		if (info->lowl != &lowl_hid && info->lowl != &lowl_usb)
+			applog(LOG_WARNING, "%s: Matched \"%s\" serial \"%s\", but lowlevel driver is not mcp2210!",
+			       __func__, product, serial);
 		return false;
 	}
 	

+ 189 - 0
lowl-hid.c

@@ -0,0 +1,189 @@
+/*
+ * Copyright 2012-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 "config.h"
+
+#ifndef WIN32
+#include <dlfcn.h>
+typedef void *dlh_t;
+#else
+#include <winsock2.h>
+#include <windows.h>
+#define dlopen(lib, flags) LoadLibrary(lib)
+#define dlsym(h, sym)  ((void*)GetProcAddress(h, sym))
+#define dlerror()  "unknown"
+#define dlclose(h)  FreeLibrary(h)
+typedef HMODULE dlh_t;
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <hidapi.h>
+#include <utlist.h>
+
+#include "logging.h"
+#include "lowlevel.h"
+#include "miner.h"
+
+struct hid_device_info HID_API_EXPORT *(*dlsym_hid_enumerate)(unsigned short, unsigned short);
+void HID_API_EXPORT (*dlsym_hid_free_enumeration)(struct hid_device_info *);
+hid_device * HID_API_EXPORT (*dlsym_hid_open_path)(const char *);
+void HID_API_EXPORT (*dlsym_hid_close)(hid_device *);
+int HID_API_EXPORT (*dlsym_hid_read)(hid_device *, unsigned char *, size_t);
+int HID_API_EXPORT (*dlsym_hid_write)(hid_device *, const unsigned char *, size_t);
+
+#define LOAD_SYM(sym)  do { \
+	if (!(dlsym_ ## sym = dlsym(dlh, #sym))) {  \
+		applog(LOG_DEBUG, "%s: Failed to load %s in %s", __func__, #sym, dlname);  \
+		goto fail;  \
+	}  \
+} while(0)
+
+static
+bool hidapi_try_lib(const char * const dlname)
+{
+	struct hid_device_info *hid_enum;
+	dlh_t dlh;
+	
+	dlh = dlopen(dlname, RTLD_NOW);
+	if (!dlh)
+	{
+		applog(LOG_DEBUG, "%s: Couldn't load %s: %s", __func__, dlname, dlerror());
+		return false;
+	}
+	
+	LOAD_SYM(hid_enumerate);
+	LOAD_SYM(hid_free_enumeration);
+	
+	hid_enum = dlsym_hid_enumerate(0, 0);
+	if (!hid_enum)
+	{
+		applog(LOG_DEBUG, "%s: Loaded %s, but no devices enumerated; trying other libraries", __func__, dlname);
+		goto fail;
+	}
+	dlsym_hid_free_enumeration(hid_enum);
+	
+	LOAD_SYM(hid_open_path);
+	LOAD_SYM(hid_close);
+	LOAD_SYM(hid_read);
+	LOAD_SYM(hid_write);
+	
+	applog(LOG_DEBUG, "%s: Successfully loaded %s", __func__, dlname);
+	
+	return true;
+
+fail:
+	dlclose(dlh);
+	return false;
+}
+
+// #defines hid_* calls, so must be after library loader
+#include "lowl-hid.h"
+
+static
+bool hidapi_load_library()
+{
+	if (dlsym_hid_write)
+		return true;
+	
+	const char **p;
+	char dlname[23] = "libhidapi";
+	const char *dltry[] = {
+		"",
+		"-0",
+		"-hidraw",
+		"-libusb",
+		NULL
+	};
+	for (p = &dltry[0]; *p; ++p)
+	{
+		sprintf(&dlname[9], "%s.%s", *p,
+#ifdef WIN32
+		        "dll"
+#else
+		        "so"
+#endif
+		);
+		if (hidapi_try_lib(dlname))
+			return true;
+	}
+	
+	return false;
+}
+
+static
+char *wcs2str_dup(wchar_t *ws)
+{
+	if (!ws)
+		return NULL;
+	
+	char *rv;
+	int clen, i;
+	
+	clen = wcslen(ws);
+	++clen;
+	rv = malloc(clen);
+	for (i = 0; i < clen; ++i)
+		rv[i] = ws[i];
+	
+	return rv;
+}
+
+static
+struct lowlevel_device_info *hid_devinfo_scan()
+{
+	if (!hidapi_load_library())
+	{
+		applog(LOG_DEBUG, "%s: Failed to load any hidapi library", __func__);
+		return NULL;
+	}
+	
+	struct hid_device_info *hid_enum, *hid_item;
+	struct lowlevel_device_info *info, *devinfo_list = NULL;
+	
+	hid_enum = hid_enumerate(0, 0);
+	if (!hid_enum)
+	{
+		applog(LOG_DEBUG, "%s: No HID devices found", __func__);
+		return NULL;
+	}
+	
+	LL_FOREACH(hid_enum, hid_item)
+	{
+		info = malloc(sizeof(struct lowlevel_device_info));
+		char * const devid = malloc(4 + strlen(hid_item->path) + 1);
+		sprintf(devid, "hid:%s", hid_item->path);
+		*info = (struct lowlevel_device_info){
+			.lowl = &lowl_hid,
+			.path = strdup(hid_item->path),
+			.devid = devid,
+			.vid = hid_item->vendor_id,
+			.pid = hid_item->product_id,
+			.manufacturer = wcs2str_dup(hid_item->manufacturer_string),
+			.product = wcs2str_dup(hid_item->product_string),
+			.serial  = wcs2str_dup(hid_item->serial_number),
+		};
+		LL_PREPEND(devinfo_list, info);
+
+		applog(LOG_DEBUG, "%s: Found \"%s\" serial \"%s\"",
+		       __func__, info->product, info->serial);
+	}
+	
+	hid_free_enumeration(hid_enum);
+	
+	return devinfo_list;
+}
+
+struct lowlevel_driver lowl_hid = {
+	.dname = "hid",
+	.devinfo_scan = hid_devinfo_scan,
+};

+ 25 - 0
lowl-hid.h

@@ -0,0 +1,25 @@
+#ifndef BFG_LOWL_HID_H
+#define BFG_LOWL_HID_H
+
+#include <hidapi.h>
+
+#ifdef WIN32
+#define HID_API_EXPORT __declspec(dllexport)
+#else
+#define HID_API_EXPORT /* */
+#endif
+extern struct hid_device_info HID_API_EXPORT *(*dlsym_hid_enumerate)(unsigned short, unsigned short);
+extern void HID_API_EXPORT (*dlsym_hid_free_enumeration)(struct hid_device_info *);
+extern hid_device * HID_API_EXPORT (*dlsym_hid_open_path)(const char *);
+extern void HID_API_EXPORT (*dlsym_hid_close)(hid_device *);
+extern int HID_API_EXPORT (*dlsym_hid_read)(hid_device *, unsigned char *, size_t);
+extern int HID_API_EXPORT (*dlsym_hid_write)(hid_device *, const unsigned char *, size_t);
+
+#define hid_enumerate dlsym_hid_enumerate
+#define hid_free_enumeration dlsym_hid_free_enumeration
+#define hid_open_path dlsym_hid_open_path
+#define hid_close dlsym_hid_close
+#define hid_read dlsym_hid_read
+#define hid_write dlsym_hid_write
+
+#endif

+ 5 - 0
lowlevel.c

@@ -74,6 +74,11 @@ void lowlevel_scan()
 	LL_CONCAT(devinfo_list, devinfo_mid_list);
 #endif
 	
+#ifdef NEED_BFG_LOWL_HID
+	devinfo_mid_list = lowl_hid.devinfo_scan();
+	LL_CONCAT(devinfo_list, devinfo_mid_list);
+#endif
+	
 #ifdef USE_NANOFURY
 	devinfo_mid_list = lowl_mcp2210.devinfo_scan();
 	LL_CONCAT(devinfo_list, devinfo_mid_list);

+ 3 - 0
lowlevel.h

@@ -44,6 +44,9 @@ extern void lowlevel_devinfo_free(struct lowlevel_device_info *);
 #ifdef USE_X6500
 extern struct lowlevel_driver lowl_ft232r;
 #endif
+#ifdef NEED_BFG_LOWL_HID
+extern struct lowlevel_driver lowl_hid;
+#endif
 #ifdef USE_NANOFURY
 extern struct lowlevel_driver lowl_mcp2210;
 #endif

+ 11 - 141
mcp2210.c

@@ -27,11 +27,11 @@ typedef HMODULE dlh_t;
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <hidapi.h>
 #include <utlist.h>
 
 #include "logging.h"
 #include "lowlevel.h"
+#include "lowl-hid.h"
 #include "miner.h"
 
 #include "mcp2210.h"
@@ -39,158 +39,28 @@ typedef HMODULE dlh_t;
 #define MCP2210_IDVENDOR   0x04d8
 #define MCP2210_IDPRODUCT  0x00de
 
-#ifdef WIN32
-#define HID_API_EXPORT __declspec(dllexport)
-#else
-#define HID_API_EXPORT /* */
-#endif
-struct hid_device_info HID_API_EXPORT *(*dlsym_hid_enumerate)(unsigned short, unsigned short);
-void HID_API_EXPORT (*dlsym_hid_free_enumeration)(struct hid_device_info *);
-hid_device * HID_API_EXPORT (*dlsym_hid_open_path)(const char *);
-void HID_API_EXPORT (*dlsym_hid_close)(hid_device *);
-int HID_API_EXPORT (*dlsym_hid_read)(hid_device *, unsigned char *, size_t);
-int HID_API_EXPORT (*dlsym_hid_write)(hid_device *, const unsigned char *, size_t);
-
-#define LOAD_SYM(sym)  do { \
-	if (!(dlsym_ ## sym = dlsym(dlh, #sym))) {  \
-		applog(LOG_DEBUG, "%s: Failed to load %s in %s", __func__, #sym, dlname);  \
-		goto fail;  \
-	}  \
-} while(0)
-
 static
-bool hidapi_try_lib(const char * const dlname)
+bool _mcp2210_devinfo_scan_cb(struct lowlevel_device_info * const usbinfo, void * const userp)
 {
-	struct hid_device_info *hid_enum;
-	dlh_t dlh;
-	
-	dlh = dlopen(dlname, RTLD_NOW);
-	if (!dlh)
-	{
-		applog(LOG_DEBUG, "%s: Couldn't load %s: %s", __func__, dlname, dlerror());
-		return false;
-	}
-	
-	LOAD_SYM(hid_enumerate);
-	LOAD_SYM(hid_free_enumeration);
-	
-	hid_enum = dlsym_hid_enumerate(0, 0);
-	if (!hid_enum)
-	{
-		applog(LOG_DEBUG, "%s: Loaded %s, but no devices enumerated; trying other libraries", __func__, dlname);
-		goto fail;
-	}
-	dlsym_hid_free_enumeration(hid_enum);
+	struct lowlevel_device_info **devinfo_list_p = userp, *info;
 	
-	LOAD_SYM(hid_open_path);
-	LOAD_SYM(hid_close);
-	LOAD_SYM(hid_read);
-	LOAD_SYM(hid_write);
-	
-	applog(LOG_DEBUG, "%s: Successfully loaded %s", __func__, dlname);
-	
-	return true;
-
-fail:
-	dlclose(dlh);
-	return false;
-}
-
-#define hid_enumerate dlsym_hid_enumerate
-#define hid_free_enumeration dlsym_hid_free_enumeration
-#define hid_open_path dlsym_hid_open_path
-#define hid_close dlsym_hid_close
-#define hid_read dlsym_hid_read
-#define hid_write dlsym_hid_write
-
-static
-bool hidapi_load_library()
-{
-	if (dlsym_hid_write)
-		return true;
-	
-	const char **p;
-	char dlname[23] = "libhidapi";
-	const char *dltry[] = {
-		"",
-		"-0",
-		"-hidraw",
-		"-libusb",
-		NULL
+	info = malloc(sizeof(*info));
+	*info = (struct lowlevel_device_info){
+		.lowl = &lowl_mcp2210,
 	};
-	for (p = &dltry[0]; *p; ++p)
-	{
-		sprintf(&dlname[9], "%s.%s", *p,
-#ifdef WIN32
-		        "dll"
-#else
-		        "so"
-#endif
-		);
-		if (hidapi_try_lib(dlname))
-			return true;
-	}
+	lowlevel_devinfo_semicpy(info, usbinfo);
+	LL_PREPEND(*devinfo_list_p, info);
 	
+	// Never *consume* the lowl_usb entry - especially since this is during the scan!
 	return false;
 }
 
-static
-char *wcs2str_dup(wchar_t *ws)
-{
-	if (!ws)
-		return NULL;
-	
-	char *rv;
-	int clen, i;
-	
-	clen = wcslen(ws);
-	++clen;
-	rv = malloc(clen);
-	for (i = 0; i < clen; ++i)
-		rv[i] = ws[i];
-	
-	return rv;
-}
-
 static
 struct lowlevel_device_info *mcp2210_devinfo_scan()
 {
-	if (!hidapi_load_library())
-	{
-		applog(LOG_DEBUG, "%s: Failed to load any hidapi library", __func__);
-		return NULL;
-	}
-	
-	struct hid_device_info *hid_enum, *hid_item;
-	struct lowlevel_device_info *info, *devinfo_list = NULL;
-	
-	hid_enum = hid_enumerate(MCP2210_IDVENDOR, MCP2210_IDPRODUCT);
-	if (!hid_enum)
-	{
-		applog(LOG_DEBUG, "%s: No MCP2210 devices found", __func__);
-		return NULL;
-	}
-	
-	LL_FOREACH(hid_enum, hid_item)
-	{
-		info = malloc(sizeof(struct lowlevel_device_info));
-		char * const devid = malloc(4 + strlen(hid_item->path) + 1);
-		sprintf(devid, "hid:%s", hid_item->path);
-		*info = (struct lowlevel_device_info){
-			.lowl = &lowl_mcp2210,
-			.path = strdup(hid_item->path),
-			.devid = devid,
-			.manufacturer = wcs2str_dup(hid_item->manufacturer_string),
-			.product = wcs2str_dup(hid_item->product_string),
-			.serial  = wcs2str_dup(hid_item->serial_number),
-		};
-		LL_PREPEND(devinfo_list, info);
-
-		applog(LOG_DEBUG, "%s: Found \"%s\" serial \"%s\"",
-		       __func__, info->product, info->serial);
-	}
+	struct lowlevel_device_info *devinfo_list = NULL;
 	
-	hid_free_enumeration(hid_enum);
+	lowlevel_detect_id(_mcp2210_devinfo_scan_cb, &devinfo_list, &lowl_hid, MCP2210_IDVENDOR, MCP2210_IDPRODUCT);
 	
 	return devinfo_list;
 }