--- cg_o/cgminer.c	2013-11-26 09:34:42.931359801 +0200
+++ cgminer/cgminer.c	2013-11-26 09:34:57.104115952 +0200
@@ -72,6 +72,22 @@
 #include "driver-bflsc.h"
 #endif
 
+#ifdef USE_HEXMINERA
+#include "driver-hexminera.h"
+#endif
+
+#ifdef USE_HEXMINERB
+#include "driver-hexminerb.h"
+#endif
+
+#ifdef USE_HEXMINERC
+#include "driver-hexminerc.h"
+#endif
+
+#ifdef USE_HEXMINERN
+#include "driver-hexminern.h"
+#endif
+
 #ifdef USE_HASHFAST
 #include "driver-hashfast.h"
 int opt_hfa_ntime_roll;
@@ -79,7 +95,7 @@
 bool opt_hfa_pll_bypass;
 #endif
 
-#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_AVALON) || defined(USE_MODMINER)
+#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_AVALON) || defined(USE_MODMINER) || defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
 #	define USE_FPGA
 #endif
 
@@ -166,13 +182,25 @@
 #ifdef USE_KLONDIKE
 char *opt_klondike_options = NULL;
 #endif
+#ifdef USE_HEXMINERA
+char *opt_hexminera_options = NULL;
+#endif
+#ifdef USE_HEXMINERB
+char *opt_hexminerb_options = NULL;
+#endif
+#ifdef USE_HEXMINERC
+char *opt_hexminerc_options = NULL;
+#endif
+#ifdef USE_HEXMINERN
+char *opt_hexminern_options = NULL;
+#endif
 #ifdef USE_USBUTILS
 char *opt_usb_select = NULL;
 int opt_usbdump = -1;
 bool opt_usb_list_all;
 cgsem_t usb_resource_sem;
 static pthread_t usb_poll_thread;
-static bool usb_polling;
+static bool usb_polling; 
 #endif
 
 char *opt_kernel_path;
@@ -256,6 +284,11 @@
 
 int total_pools, enabled_pools;
 enum pool_strategy pool_strategy = POOL_FAILOVER;
+
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC)
+enum default_hex_miner default_hex_miner = D_HEXA;
+#endif
+
 int opt_rotate_period;
 static int total_urls, total_users, total_passes, total_userpasses;
 
@@ -639,7 +672,7 @@
 	return set_int_range(arg, i, 0, 10);
 }
 
-#ifdef USE_AVALON
+#if defined(USE_AVALON) || defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
 static char *set_int_0_to_100(const char *arg, int *i)
 {
 	return set_int_range(arg, i, 0, 100);
@@ -715,6 +748,32 @@
 	return NULL;
 }
 
+
+#ifdef USE_HEXMINERA
+static char *set_default_to_a(enum default_hex_miner *which)
+{
+	*which = D_HEXA;
+	return NULL;
+}
+#endif
+
+
+#ifdef USE_HEXMINERB
+static char *set_default_to_b(enum default_hex_miner *which)
+{
+	*which = D_HEXB;
+	return NULL;
+}
+#endif
+
+#ifdef USE_HEXMINERC
+static char *set_default_to_c(enum default_hex_miner *which)
+{
+	*which = D_HEXC;
+	return NULL;
+}
+#endif
+
 static char *set_balance(enum pool_strategy *strategy)
 {
 	*strategy = POOL_BALANCE;
@@ -1052,6 +1111,41 @@
 }
 #endif
 
+
+#ifdef USE_HEXMINERA
+static char *set_hexminera_options(const char *arg)
+{
+	opt_set_charp(arg, &opt_hexminera_options);
+
+	return NULL;
+}
+#endif
+
+#ifdef USE_HEXMINERB
+static char *set_hexminerb_options(const char *arg)
+{
+	opt_set_charp(arg, &opt_hexminerb_options);
+
+	return NULL;
+}
+#endif
+
+#ifdef USE_HEXMINERC
+static char *set_hexminerc_options(const char *arg)
+{
+	opt_set_charp(arg, &opt_hexminerc_options);
+
+	return NULL;
+}
+#endif
+#ifdef USE_HEXMINERN
+static char *set_hexminern_options(const char *arg)
+{
+	opt_set_charp(arg, &opt_hexminern_options);
+
+	return NULL;
+}
+#endif
 #ifdef USE_USBUTILS
 static char *set_usb_select(const char *arg)
 {
@@ -1214,6 +1308,44 @@
 		     set_klondike_options, NULL, NULL,
 		     "Set klondike options clock:temptarget"),
 #endif
+#ifdef USE_HEXMINERA
+	OPT_WITH_ARG("--hexminera-options",
+		     set_hexminera_options, NULL, NULL,
+		     "Set HEXMinerA options asic_count:freq"),
+	OPT_WITH_ARG("--hexminera-voltage",
+		     libhexa_set_config_voltage, NULL, NULL,
+		     "Set HEXMinerA core voltage, in millivolts"),
+	OPT_WITHOUT_ARG("--set_default_to_a",
+		     set_default_to_a, &default_hex_miner,
+		     "Handle USB detect errors as hexA"),
+#endif
+#ifdef USE_HEXMINERB
+	OPT_WITH_ARG("--hexminerb-options",
+		     set_hexminerb_options, NULL, NULL,
+		     "Set HEXMinerB options asic_count:freq"),
+	OPT_WITH_ARG("--hexminerb-voltage",
+		     libhexb_set_config_voltage, NULL, NULL,
+		     "Set HEXMinerB core voltage, in millivolts"),
+  OPT_WITHOUT_ARG("--set_default_to_b",
+		     set_default_to_b, &default_hex_miner,
+		     "Handle USB detect errors as hexB"),
+#endif
+#ifdef USE_HEXMINERC
+	OPT_WITH_ARG("--hexminerc-options",
+		     set_hexminerc_options, NULL, NULL,
+		     "Set HEXMinerC options asic_count:freq"),
+	OPT_WITH_ARG("--hexminerc-voltage",
+		     libhexc_set_config_voltage, NULL, NULL,
+		     "Set HEXMinerC core voltage, in millivolts"),
+  OPT_WITHOUT_ARG("--set_default_to_c",
+		     set_default_to_c, &default_hex_miner,
+		     "Handle USB detect errors as hexC"),
+#endif
+#ifdef USE_HEXMINERN
+	OPT_WITH_ARG("--hexminern-options",
+		     set_hexminern_options, NULL, NULL,
+		     "Set HEXMinerN options voltage:freq"),
+#endif
 	OPT_WITHOUT_ARG("--load-balance",
 		     set_loadbalance, &pool_strategy,
 		     "Change multipool strategy from failover to quota based balance"),
@@ -1537,6 +1669,18 @@
 #ifdef USE_BAB
 		"BaB "
 #endif
+#ifdef USE_HEXMINERA
+		"hexminera "
+#endif
+#ifdef USE_HEXMINERB
+		"hexminerb "
+#endif
+#ifdef USE_HEXMINERC
+		"hexminerc "
+#endif
+#ifdef USE_HEXMINERN
+		"hexminern "
+#endif
 #ifdef USE_MODMINER
 		"modminer "
 #endif
@@ -2063,7 +2207,7 @@
 
 /* Convert a uint64_t value into a truncated string for displaying with its
  * associated suitable for Mega, Giga etc. Buf array needs to be long enough */
-static void suffix_string(uint64_t val, char *buf, size_t bufsiz, int sigdigits)
+void suffix_string(uint64_t val, char *buf, size_t bufsiz, int sigdigits)
 {
 	const double  dkilo = 1000.0;
 	const uint64_t kilo = 1000ull;
@@ -2136,12 +2280,12 @@
 		dev_runtime = 1.0;
 
 	wu = cgpu->diff1 / dev_runtime * 60.0;
-
+	
 	dh64 = (double)cgpu->total_mhashes / dev_runtime * 1000000ull;
 	dr64 = (double)cgpu->rolling * 1000000ull;
 	suffix_string(dh64, displayed_hashes, sizeof(displayed_hashes), 4);
 	suffix_string(dr64, displayed_rolling, sizeof(displayed_rolling), 4);
-
+	
 	snprintf(buf, bufsiz, "%s%d ", cgpu->drv->name, cgpu->device_id);
 	cgpu->drv->get_statline_before(buf, bufsiz, cgpu);
 	tailsprintf(buf, bufsiz, "(%ds):%s (avg):%sh/s | A:%.0f R:%.0f HW:%d WU:%.1f/m",
@@ -2223,7 +2367,7 @@
 
 static void curses_print_devstatus(struct cgpu_info *cgpu, int count)
 {
-	static int dawidth = 1, drwidth = 1, hwwidth = 1, wuwidth = 1;
+	static int dawidth = 1, drwidth = 1, hwwidth = 1,hwwidthp = 1, wuwidth = 1;
 	char logline[256];
 	char displayed_hashes[16], displayed_rolling[16];
 	uint64_t dh64, dr64;
@@ -2251,7 +2395,10 @@
 
 	cgpu->utility = cgpu->accepted / dev_runtime * 60;
 	wu = cgpu->diff1 / dev_runtime * 60;
-
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+	double hwp = (cgpu->hw_errors + cgpu->diff1) ?
+		     (double)100 *(double)(cgpu->hw_errors) / (double)(cgpu->hw_errors + cgpu->diff1) : 0;
+#endif
 	wmove(statuswin,devcursor + count, 0);
 	cg_wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id);
 	logline[0] = '\0';
@@ -2281,14 +2428,35 @@
 	adj_fwidth(cgpu->diff_accepted, &dawidth);
 	adj_fwidth(cgpu->diff_rejected, &drwidth);
 	adj_width(cgpu->hw_errors, &hwwidth);
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+	if(usb_ident(cgpu) == IDENT_HEXA || usb_ident(cgpu) == IDENT_HEXB || usb_ident(cgpu) == IDENT_HEXC || usb_ident(cgpu) == IDENT_HEXN) adj_width(hwp, &hwwidthp);
+#endif
 	adj_width(wu, &wuwidth);
-
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+	if(usb_ident(cgpu) == IDENT_HEXA || usb_ident(cgpu) == IDENT_HEXB || usb_ident(cgpu) == IDENT_HEXC || usb_ident(cgpu) == IDENT_HEXN) {
+		cg_wprintw(statuswin, "/%6sh/s | A:%*.0f R:%*.0f HW:%*d/%*.2f%% WU:%*.1f/m",
+				displayed_hashes,
+				dawidth, cgpu->diff_accepted,
+				drwidth, cgpu->diff_rejected,
+				hwwidth, cgpu->hw_errors,
+				hwwidthp +1, hwp,
+				wuwidth + 2, wu);
+	} else {
+		cg_wprintw(statuswin, "/%6sh/s | A:%*.0f R:%*.0f HW:%*d WU:%*.1f/m",
+			displayed_hashes,
+			dawidth, cgpu->diff_accepted,
+			drwidth, cgpu->diff_rejected,
+			hwwidth, cgpu->hw_errors,
+			wuwidth + 2, wu);
+	}
+#else
 	cg_wprintw(statuswin, "/%6sh/s | A:%*.0f R:%*.0f HW:%*d WU:%*.1f/m",
 			displayed_hashes,
 			dawidth, cgpu->diff_accepted,
 			drwidth, cgpu->diff_rejected,
 			hwwidth, cgpu->hw_errors,
 			wuwidth + 2, wu);
+#endif
 
 	logline[0] = '\0';
 	cgpu->drv->get_statline(logline, sizeof(logline), cgpu);
@@ -3914,7 +4082,10 @@
 	/* Cancels any cancellable usb transfers. Flagged as such it means they
 	 * are usualy waiting on a read result and it's safe to abort the read
 	 * early. */
+	#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+	#else
 	cancel_usb_transfers();
+	#endif
 #endif
 	return NULL;
 }
@@ -5770,6 +5941,7 @@
 
 	/* Signal hash_pop again in case there are mutliple hash_pop waiters */
 	pthread_cond_signal(&getq->cond);
+	//pthread_cond_broadcast(&getq->cond);
 	mutex_unlock(stgd_lock);
 
 	return work;
@@ -6050,7 +6222,9 @@
 	update_work_stats(thr, work);
 
 	if (!fulltest(work->hash, work->target)) {
-		applog(LOG_INFO, "Share above target");
+		//applog(LOG_INFO, "Share above target");
+		applog(LOG_INFO, "%s%d: Share above target",
+			thr->cgpu->drv->name, thr->cgpu->device_id);
 		return;
 	}
 	work_out = copy_work(work);
@@ -6088,7 +6262,10 @@
 	ret = true;
 	update_work_stats(thr, work);
 	if (!fulltest(work->hash, work->target)) {
-		applog(LOG_INFO, "Share above target");
+		//applog(LOG_INFO, "Share above target");
+		applog(LOG_INFO, "%s%d: Share above target",
+			thr->cgpu->drv->name, thr->cgpu->device_id);
+		
 		goto  out;
 	}
 	submit_work_async(work);
@@ -6144,9 +6321,10 @@
 	while (likely(!cgpu->shutdown)) {
 		struct work *work = get_work(mythr, thr_id);
 		int64_t hashes;
-
+		
 		mythr->work_restart = false;
 		cgpu->new_work = true;
+		
 
 		cgtime(&tv_workstart);
 		work->nonce = 0;
@@ -6466,6 +6644,7 @@
 		free_work(work);
 		applog(LOG_DEBUG, "Discarded queued work item");
 	}
+	
 }
 
 /* This version of hash work is for devices that are fast enough to always
@@ -6483,17 +6662,18 @@
 	while (likely(!cgpu->shutdown)) {
 		struct timeval diff;
 		int64_t hashes;
-
+    
 		mythr->work_update = false;
-
+  	
 		fill_queue(mythr, cgpu, drv, thr_id);
 
 		hashes = drv->scanwork(mythr);
 
 		/* Reset the bool here in case the driver looks for it
 		 * synchronously in the scanwork loop. */
+		
 		mythr->work_restart = false;
-
+  	
 		if (unlikely(hashes == -1 )) {
 			applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id);
 			cgpu->deven = DEV_DISABLED;
@@ -6515,7 +6695,7 @@
 		if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED))
 			mt_disable(mythr, thr_id, drv);
 
-		if (mythr->work_update)
+ 		if (mythr->work_update)
 			drv->update_work(cgpu);
 	}
 	cgpu->deven = DEV_DISABLED;
@@ -6536,15 +6716,16 @@
 	while (likely(!cgpu->shutdown)) {
 		struct timeval diff;
 		int64_t hashes;
-
+   
 		mythr->work_update = false;
-
+   
 		hashes = drv->scanwork(mythr);
 
 		/* Reset the bool here in case the driver looks for it
 		 * synchronously in the scanwork loop. */
+		
 		mythr->work_restart = false;
-
+		
 		if (unlikely(hashes == -1 )) {
 			applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id);
 			cgpu->deven = DEV_DISABLED;
@@ -6566,7 +6747,7 @@
 		if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED))
 			mt_disable(mythr, thr_id, drv);
 
-		if (mythr->work_update)
+    if (mythr->work_update)
 			drv->update_work(cgpu);
 	}
 	cgpu->deven = DEV_DISABLED;
@@ -7220,9 +7401,12 @@
 static void clean_up(bool restarting)
 {
 #ifdef USE_USBUTILS
-	usb_polling = false;
-	pthread_join(usb_poll_thread, NULL);
-        libusb_exit(NULL);
+ usb_polling = false;
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+#else
+ pthread_join(usb_poll_thread, NULL);      
+#endif
+ libusb_exit(NULL);
 #endif
 
 	cgtime(&total_tv_end);
@@ -7791,6 +7975,126 @@
 #define DRIVER_DRV_DETECT_ALL(X) X##_drv.drv_detect(false);
 
 #ifdef USE_USBUTILS
+//UGLY but if hotplug is ok we are disabling it. Something is happening here and we do not need it.
+//This breaks badly cgminer code (MIPS - TPLINK) and other device support but whoever wants please do enable it.
+//What happens is that for some reason pooling touches usbdev even though reads/writes are performed under lock like in usb-utils
+// same function actualy
+
+/*
+
+(gdb) c
+Continuing.
+[New Thread 887]
+
+Program received signal SIGSEGV, Segmentation fault.
+[Switching to Thread 887]
+usbi_hotplug_match (dev=0x3, event=(unknown: 0)) at hotplug.c:166
+166             struct libusb_context *ctx = dev->ctx;
+(gdb) bt full
+#0  usbi_hotplug_match (dev=0x3, event=(unknown: 0)) at hotplug.c:166
+        hotplug_cb = <optimized out>
+        next = <optimized out>
+        ctx = <optimized out>
+#1  0x0043f43c in handle_events (ctx=0x468258, tv=0x767f76d8) at io.c:1954
+        message = {event = (unknown: 0), device = 0x3}
+        ret = <optimized out>
+        r = 2
+        ipollfd = 0x4682e8
+        nfds = 7
+        fds = 0x70fce8
+        i = <optimized out>
+        timeout_ms = <optimized out>
+        __FUNCTION__ = "handle_events"
+#2  0x0043fcbc in libusb_handle_events_timeout_completed (ctx=0x468258, tv=<optimized out>, completed=0x767f7738) at io.c:2070
+        r = 0
+        poll_timeout = {tv_sec = 60, tv_usec = 0}
+#3  0x0043fd88 in libusb_handle_events_completed (ctx=<optimized out>, completed=<optimized out>) at io.c:2169
+        tv = {tv_sec = 60, tv_usec = 0}
+#4  0x00440468 in do_sync_bulk_transfer (dev_handle=0x47d390, endpoint=<optimized out>, buffer=<optimized out>, length=1, transferred=0x767f77b0,
+    timeout=0, type=2 '\002') at sync.c:182
+        transfer = 0x723f4c
+        completed = 0
+        r = 0
+        __FUNCTION__ = "do_sync_bulk_transfer"
+#5  0x00440810 in libusb_bulk_transfer (dev_handle=<optimized out>, endpoint=<optimized out>, data=<optimized out>, length=<optimized out>,
+    transferred=0x767f77b0, timeout=0) at sync.c:270
+No locals.
+#6  0x00434bd8 in libhexa_readHashData (hash_write_pos=<synthetic pointer>, hash=0x767f77d4 "S\fR", hexminera=0x479098, timeout=<optimized out>,
+    read_once=<optimized out>) at libhexa.c:354
+        info = <optimized out>
+        read = 0
+        err = 0
+        timeout = 0
+        usbdev = 0x47b338
+        read_once = true
+        total = <optimized out>
+#7  hexminera_get_results (userdata=0x479098) at driver-hexminera.c:462
+        ts_start = {tv_sec = 11437, tv_nsec = 862254175}
+        hexminera = 0x479098
+        info = 0x47d410
+        readbuf = "S\fR\000\060\025\307A\314\336\000\023\a\000\000\000\000\021", '\000' <repeats 11 times>, "\323S\002R\224d\025\307AÌS\004R\234dC\000O\000O\000\000\000\212S\001W\000@.\000\031S\001R\004\060\336\000\270S\001R\004\060\336\000\270S\001R\000h\024\a)S\fR\000\060z\257\255\351\337\000\022\a\000\000\000\000\021", '\000' <repeats 11 times>, "\251S\002R\224dz\257\255\351^S\004R\234dC\000O\000O\000\000\000\212S\001W\000@.\000\031S\001R\004\060\337\000\271S\001R\004\060\337\000\271S\001R\000h\024\a)S\004R\234dC\000O\000O\000\000\000\212S\001W\000@.\000\031S\001R\004\060\337\000"...
+        wr = 0x49f2a8
+        array_nonce_cache = 0x4ac7c8
+        thr = 0x472840
+        i = <optimized out>
+        lastchippos = 10
+        nonce = <optimized out>
+        found = <optimized out>
+        usb_r_reset = 0
+        threadname = "hexa_recv/1", '\000' <repeats 12 times>
+        ret_r = <optimized out>
+        hash_read_pos = 256
+        hash_write_pos = 258
+        need_work_reset = 0
+        __func__ = "hexminera_get_results"
+---Type <return> to continue, or q <return> to quit---
+#8  0x77eefc94 in start_thread (arg=0x767f8530) at libpthread/nptl/pthread_create.c:297
+        pd = 0x767f8530
+        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {{__pc = 0x77eefbb8 <start_thread+184>, __sp = 0x767f8020, __regs = {1988068656, 2012246048, 2012174776,
+                    1988067584, 0, 0, 4096, 2097152}, __fp = 0x767f8020, __gp = 0x77ec33b0, __fpc_csr = 0, __fpregs = {0, 0, 0, 0, 0, 0}}},
+              mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
+        not_first_call = 0
+        robust = <optimized out>
+        pagesize_m1 = <optimized out>
+        sp = 0x767f8020 ""
+        freesize = <optimized out>
+#9  0x77ee80e0 in __thread_start () at ./libc/sysdeps/linux/mips/clone.S:146
+No locals.
+Backtrace stopped: frame did not save the PC
+
+
+Program received signal SIG32, Real-time event 32.
+[Switching to Thread 978]
+clock_nanosleep (clock_id=1, flags=1, req=0x751f7fa8, rem=0x0) at librt/clock_nanosleep.c:51
+51            LIBC_CANCEL_RESET (oldstate);
+(gdb) bt full
+#0  clock_nanosleep (clock_id=1, flags=1, req=0x751f7fa8, rem=0x0) at librt/clock_nanosleep.c:51
+        oldstate = 2
+        err = <optimized out>
+        r = <optimized out>
+#1  0x0041e238 in nanosleep_abstime (ts_end=0x751f7fa8) at util.c:1001
+        ret = 514
+#2  0x00420aa0 in cgsleep_ms_r (ts_start=0x751f7fd0, ms=<optimized out>) at util.c:1014
+        ts_end = {tv_sec = 11737, tv_nsec = 388217180}
+#3  0x00420b10 in cgsleep_ms (ms=5000) at util.c:1155
+        ts_start = {tv_sec = 11732, tv_nsec = 388217180}
+#4  0x0041cb94 in hotplug_thread (userdata=<optimized out>) at cgminer.c:7979
+No locals.
+#5  0x77eefc94 in start_thread (arg=0x751f8530) at libpthread/nptl/pthread_create.c:297
+        pd = 0x751f8530
+        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {{__pc = 0x77eefbb8 <start_thread+184>, __sp = 0x751f8020, __regs = {1964999984, 2012246048, 2012174776,
+                    1964998912, 0, 0, 4096, 2097152}, __fp = 0x751f8020, __gp = 0x77ec33b0, __fpc_csr = 0, __fpregs = {0, 0, 0, 0, 0, 0}}},
+              mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
+        not_first_call = 0
+        robust = <optimized out>
+        pagesize_m1 = <optimized out>
+        sp = 0x751f8020 ""
+        freesize = <optimized out>
+#6  0x77ee80e0 in __thread_start () at ./libc/sysdeps/linux/mips/clone.S:146
+No locals.
+Backtrace stopped: frame did not save the PC
+*/
+
 static void *libusb_poll_thread(void __maybe_unused *arg)
 {
 	struct timeval tv_end = {1, 0};
@@ -7823,7 +8127,11 @@
 	mutex_init(&cgusbres_lock);
 	cglock_init(&cgusb_fd_lock);
 	usb_polling = true;
+	#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB)  || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+	#else
+	
 	pthread_create(&usb_poll_thread, NULL, libusb_poll_thread, NULL);
+	#endif
 }
 #else
 #define initialise_usb() {}
--- cg_o/configure.ac	2013-11-26 09:34:42.935360014 +0200
+++ cgminer/configure.ac	2013-11-26 09:34:57.140117451 +0200
@@ -225,6 +225,50 @@
 fi
 AM_CONDITIONAL([HAS_KNC], [test x$knc = xyes])
 
+hexminera="no"
+
+AC_ARG_ENABLE([hexminera],
+	[AC_HELP_STRING([--enable-hexminera],[Compile support for hexminera (default disabled)])],
+	[hexminera=$enableval]
+	)
+if test "x$hexminera" = xyes; then
+	AC_DEFINE([USE_HEXMINERA], [1], [Defined to 1 if hexminera support is wanted])
+fi
+AM_CONDITIONAL([HAS_HEXMINERA], [test x$hexminera = xyes])
+
+hexminerb="no"
+
+AC_ARG_ENABLE([hexminerb],
+	[AC_HELP_STRING([--enable-hexminerb],[Compile support for hexminerb (default disabled)])],
+	[hexminerb=$enableval]
+	)
+if test "x$hexminerb" = xyes; then
+	AC_DEFINE([USE_HEXMINERB], [1], [Defined to 1 if hexminerb support is wanted])
+fi
+AM_CONDITIONAL([HAS_HEXMINERB], [test x$hexminerb = xyes])
+
+hexminern="no"
+
+AC_ARG_ENABLE([hexminern],
+	[AC_HELP_STRING([--enable-hexminern],[Compile support for hexminern (default disabled)])],
+	[hexminern=$enableval]
+	)
+if test "x$hexminern" = xyes; then
+	AC_DEFINE([USE_HEXMINERN], [1], [Defined to 1 if hexminern support is wanted])
+fi
+AM_CONDITIONAL([HAS_HEXMINERN], [test x$hexminern = xyes])
+
+hexminerc="no"
+
+AC_ARG_ENABLE([hexminerc],
+	[AC_HELP_STRING([--enable-hexminerc],[Compile support for hexminerc (default disabled)])],
+	[hexminerc=$enableval]
+	)
+if test "x$hexminerc" = xyes; then
+	AC_DEFINE([USE_HEXMINERC], [1], [Defined to 1 if hexminerc support is wanted])
+fi
+AM_CONDITIONAL([HAS_HEXMINERC], [test x$hexminerc = xyes])
+
 modminer="no"
 
 AC_ARG_ENABLE([modminer],
@@ -260,7 +304,7 @@
 	])
 fi
 
-if test x$avalon$bitforce$bitfury$modminer$bflsc$icarus$hashfast$klondike != xnononononononono; then
+if test x$hexminera$hexminerb$hexminerc$hexminern$avalon$bitforce$bitfury$modminer$bflsc$icarus$hashfast$klondike != xnononononononono; then
 	want_usbutils=true
 else
 	want_usbutils=false
@@ -453,6 +497,30 @@
 	echo "  BlackArrow.ASICs.....: Disabled"
 fi
 
+if test "x$hexminera" = xyes; then
+	echo "  HEX16A.ASICs.........: Enabled"
+else
+	echo "  HEX16A.ASICs.........: Disabled"
+fi
+
+if test "x$hexminerb" = xyes; then
+	echo "  HEX16B.ASICs.........: Enabled"
+else
+	echo "  HEX16B.ASICs.........: Disabled"
+fi
+
+if test "x$hexminerc" = xyes; then
+	echo "  HEX16C.ASICs.........: Enabled"
+else
+	echo "  HEX16C.ASICs.........: Disabled"
+fi
+
+if test "x$hexminern" = xyes; then
+	echo "  HEX16N.ASICs.........: Enabled"
+else
+	echo "  HEX16N.ASICs.........: Disabled"
+fi
+
 if test "x$bflsc" = xyes; then
 	echo "  BFL.ASICs............: Enabled"
 else
@@ -501,7 +569,7 @@
 	echo "  ModMiner.FPGAs.......: Disabled"
 fi
 
-if test "x$avalon$bab$bflsc$bitforce$bitfury$hashfast$icarus$klondike$knc$modminer" = xnononononononononono; then
+if test "x$hexminera$hexminerb$hexminerc$hexminern$avalon$bab$bflsc$bitforce$bitfury$hashfast$icarus$klondike$knc$modminer" = xnononononononononono; then
 	AC_MSG_ERROR([No mining configured in])
 fi
 
--- cg_o/driver-hexminerb.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/driver-hexminerb.c	2013-11-26 09:34:57.144117643 +0200
@@ -0,0 +1,603 @@
+/*$T indentinput.c GC 1.140 10/16/13 10:19:47 */
+/*
+ * Copyright 2013 Con Kolivas <kernel@kolivas.org> Copyright 2012-2013 Xiangfu
+ * <xiangfu@openmobilefree.com> Copyright 2012 Luke Dashjr Copyright 2012 Andrew
+ * Smith 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. Thank you guys!
+ */
+#include "config.h"
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <unistd.h>
+#ifndef WIN32
+#include <sys/select.h>
+#include <termios.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifndef O_CLOEXEC
+#define O_CLOEXEC	0
+#endif
+#else
+#include "compat.h"
+#include <windows.h>
+#include <io.h>
+#endif
+#include "elist.h"
+#include "miner.h"
+#include "usbutils.h"
+#include "driver-hexminerb.h"
+#include "util.h"
+
+static int option_offset = -1;
+struct device_drv hexminerb_drv;
+int opt_hexminerb_core_voltage = HEXB_DEFAULT_CORE_VOLTAGE;
+#include "libhexb.c"
+/*
+    We use a replacement algorithm to only remove references to work done from the buffer when we need the extra space
+    for new work. Thanks to Avalon code with some mods
+ */
+
+static void
+hexminerb_flush_work(struct cgpu_info *hexminerb)
+{
+	struct hexminerb_info *info = hexminerb->device_data;
+	cgsem_post(&info->qsem);
+}
+
+static int
+hexminerb_send_task (struct hexminerb_task *ht, struct cgpu_info *hexminerb)
+{
+  unsigned char buf[HEXMINERB_TASK_SIZE + 6];
+  int ret, amount = 0;
+  struct hexminerb_info *info;
+  size_t nr_len = HEXMINERB_TASK_SIZE + 6;
+  uint16_t workqueue_adr = htole16 (HEXB_WORKQUEUE_ADR);
+  buf[0] = 0x53;
+  buf[2] = 0x57;                /* Write Command - char 'W' (0x57) */
+  info = hexminerb->device_data;
+  libhexb_setvoltage (info->core_voltage, &ht->refvoltage);
+  ht->chipcount = htole16 (info->asic_count);
+  ht->hashclock = htole16 ((uint16_t) info->frequency);
+  memcpy (buf + 5, ht, HEXMINERB_TASK_SIZE);
+/* Count Words */
+  buf[1] = (uint8_t) ((HEXMINERB_TASK_SIZE) / 2);
+  memcpy (buf + 3, &workqueue_adr, 2);
+  libhexb_csum (buf, buf + HEXMINERB_TASK_SIZE + 5,
+                buf + HEXMINERB_TASK_SIZE + 5);
+                
+  if (info->wr_status != HEXB_STAT_IDLE) 
+  	return nr_len;
+  //if(info->start_up) cgsleep_ms(hexminerb->device_id * HEXB_MAX_START_DELAY_MS);
+  ret = libhexb_sendHashData (hexminerb, buf, nr_len);
+  if (ret != nr_len)
+    {
+      libhexb_reset (hexminerb);
+      mutex_lock (&info->lock);
+      info->usb_w_errors++;
+      mutex_unlock (&info->lock);
+      return -1;
+    }
+  if (info->reset_work)
+    {
+    	mutex_lock (&info->lock);
+    	//info->start_up  = false;
+      info->reset_work = false;
+      mutex_unlock (&info->lock);
+      
+    }
+  return ret;
+}
+
+static inline void
+hexminerb_create_task (bool reset_work, struct hexminerb_task *ht, struct work *work)
+{
+	if (reset_work)
+    {
+      ht->status = HEXB_STAT_NEW_WORK_CLEAR_OLD;
+    }
+  else
+    {
+      ht->status = HEXB_STAT_NEW_WORK;
+    }
+  memcpy (ht->midstate, work->midstate, 32);
+  memcpy (ht->merkle, work->data + 64, 12);
+  ht->id = (uint8_t) work->subid;
+  BITFURY_MS3compute (work, ht);
+}
+
+static void *
+hexminerb_send_tasks (void *userdata)
+{
+  struct cgpu_info *hexminerb = (struct cgpu_info *) userdata;
+  struct hexminerb_info *info = hexminerb->device_data;
+  char threadname[24];
+  snprintf (threadname, 24, "hexb_send/%d", hexminerb->device_id);
+  RenameThread (threadname);
+  libhexb_reset (hexminerb);
+  while (!libhexb_usb_dead(hexminerb))
+    {
+    	int start_count, end_count, ret;
+      cgtimer_t ts_start;
+      struct hexminerb_task ht;
+      cgsleep_prepare_r (&ts_start);
+      mutex_lock (&info->lock);
+      start_count = info->read_pos;
+      end_count =
+        info->read_pos + MIN (info->cg_queue_cached_works,
+                              HEXMINERB_ARRAY_MAX_POP);
+         
+         while (info->read_pos < HEXMINERB_ARRAY_SIZE_REAL && info->hexworks[info->read_pos] != NULL &&
+         		start_count < end_count && info->wr_status == HEXB_STAT_IDLE)
+        {
+              hexminerb_create_task (info->reset_work, &ht, info->hexworks[info->read_pos++]);
+              info->cg_queue_cached_works--;
+              mutex_unlock (&info->lock);
+             
+              ret = hexminerb_send_task (&ht, hexminerb);
+              
+              mutex_lock (&info->lock);
+              start_count++;
+        }
+      
+        mutex_unlock (&info->lock); 
+      
+      cgsem_post(&info->qsem);
+      cgsleep_us_r (&ts_start, info->usb_timing);
+    }
+  
+  pthread_exit (NULL);
+}
+
+static struct cgpu_info
+*hexminerb_detect_one (libusb_device * dev, struct usb_find_devices *found)
+{
+  
+  int miner_count, asic_count, frequency;
+  int this_option_offset = ++option_offset;
+  struct hexminerb_info *info;
+  struct cgpu_info *hexminerb;
+  bool configured;
+  int i = 0;
+  
+  hexminerb = usb_alloc_cgpu (&hexminerb_drv, HEXB_MINER_THREADS);
+  if (!usb_init (hexminerb, dev, found)) {
+  	 usb_uninit(hexminerb);
+    return NULL;
+  }  
+  hexminerb->device_data = calloc (sizeof (struct hexminerb_info), 1);
+  
+    if (unlikely (!(hexminerb->device_data))) {
+      hexminerb->device_data = NULL;
+      usb_uninit(hexminerb);
+      return NULL;
+  }
+  configured =
+    libhexb_get_options (this_option_offset, &asic_count, &frequency);
+  if (opt_hexminerb_core_voltage < HEXB_MIN_COREMV
+      || opt_hexminerb_core_voltage > HEXB_MAX_COREMV)
+    {
+      
+      applog
+        (LOG_ERR,
+         "Invalid hexminerb-voltage %d must be %dmV - %dmV",
+         opt_hexminerb_core_voltage, HEXB_MIN_COREMV, HEXB_MAX_COREMV);
+        free(hexminerb->device_data);
+            hexminerb->device_data = NULL;
+      			usb_uninit(hexminerb);
+      			return NULL;
+    }
+  info = hexminerb->device_data;
+  info->hexworks = calloc (sizeof (struct work *), HEXMINERB_ARRAY_SIZE);
+  if (unlikely (!(info->hexworks))) {
+     				free(hexminerb->device_data);
+            hexminerb->device_data = NULL;
+      			usb_uninit(hexminerb);
+      			return NULL;
+  }
+  while (i < HEXMINERB_ARRAY_SIZE) info->hexworks[i++] = NULL; 
+  info->reset_work = true;
+  //info->start_up  = true;
+  info->usb_timing = HEXB_USB_TIMING;
+  info->wr_status = HEXB_STAT_IDLE;
+  info->miner_count = HEXB_DEFAULT_MINER_NUM;
+  info->asic_count = HEXB_DEFAULT_ASIC_NUM;
+  info->frequency = HEXB_DEFAULT_FREQUENCY;
+  info->pic_voltage_readings = HEXB_DEFAULT_CORE_VOLTAGE;
+  info->core_voltage = opt_hexminerb_core_voltage;
+  if (configured)
+    {
+      info->asic_count = asic_count;
+      info->frequency = frequency;
+    }
+  if (!add_cgpu (hexminerb)) {
+  	    free(info->hexworks);
+  	        free(hexminerb->device_data);
+            hexminerb->device_data = NULL;
+            hexminerb = usb_free_cgpu (hexminerb);
+      			usb_uninit(hexminerb);
+      			return NULL;
+  }
+  return hexminerb;
+}
+
+static void
+hexminerb_detect (bool __maybe_unused hotplug)
+{
+  usb_detect (&hexminerb_drv, hexminerb_detect_one);
+}
+
+static void
+do_hexminerb_close (struct thr_info *thr)
+{
+  struct cgpu_info *hexminerb = thr->cgpu;
+  struct hexminerb_info *info = hexminerb->device_data;
+  int i = 0;
+  pthread_join (info->read_thr, NULL);
+  pthread_join (info->write_thr, NULL);
+  pthread_mutex_destroy (&info->lock);
+  
+  cgsem_destroy(&info->qsem);
+  while (i < HEXMINERB_ARRAY_SIZE) {
+  	if(info->hexworks[i] != NULL) free_work(info->hexworks[i]);
+  	i++;
+  }
+  free (info->hexworks);
+  //usb_uninit(hexminerb);
+  //Hotplug fucks on full mem free :) 
+  //free (hexminerb->device_data);
+  //hexminerb->device_data = NULL;
+  //thr->cgpu = usb_free_cgpu(hexminerb);
+  
+}
+
+static void
+hexminerb_shutdown (struct thr_info *thr)
+{
+  struct cgpu_info *hexminerb = thr->cgpu;
+  struct hexminerb_info *info = hexminerb->device_data;
+  
+  if (!hexminerb->shutdown) hexminerb->shutdown = true;
+  
+  cgsem_post(&info->qsem);
+  do_hexminerb_close (thr);
+}
+
+static void *
+hexminerb_get_results (void *userdata)
+{
+  struct cgpu_info *hexminerb = (struct cgpu_info *) userdata;
+  struct hexminerb_info *info = hexminerb->device_data;
+  unsigned char readbuf[HEXB_HASH_BUF_SIZE];
+  struct workb_result *wr;
+  struct chip_resultsb *array_nonce_cache;
+  struct thr_info *thr = info->thr;
+  
+  uint32_t nonce;
+  int found;
+  char threadname[24];
+  int need_work_reset = 0, ret_r = 0, hash_read_pos = 0, hash_write_pos = 0, amount = 0, usb_r_reset = 0;
+  float auto_times = 0, busy_times = 0, a_count = 0, a_val = 0, err_rate = 0;
+  wr = (struct workb_result *) malloc (sizeof (struct workb_result));
+  array_nonce_cache = calloc (16, sizeof (struct chip_resultsb));
+  bzero(array_nonce_cache, 16 * sizeof (struct chip_resultsb));
+  bzero(wr, sizeof (struct workb_result));
+  snprintf (threadname, 24, "hexb_recv/%d", hexminerb->device_id);
+  RenameThread (threadname);
+  while (!libhexb_usb_dead(hexminerb))
+    {
+      found = true;
+      cgtimer_t ts_start;
+      cgsleep_prepare_r (&ts_start);
+      /* Rotate */
+      ret_r = 0;
+      if (hash_write_pos + HEXB_USB_R_SIZE >= HEXB_HASH_BUF_SIZE)
+        {
+          hash_write_pos = hash_write_pos - hash_read_pos;
+          memcpy (readbuf, readbuf + hash_read_pos, hash_write_pos);
+          hash_read_pos = 0;
+        }
+      if (hash_write_pos - hash_read_pos >= HEXB_BASE_WORK_SIZE + 2)
+        {
+        	again:
+          ret_r =
+            libhexb_eatHashData (wr, readbuf, &hash_read_pos,
+                                 &hash_write_pos);
+          if (ret_r == 1 && wr->status < HEXB_STAT_UNUSED)
+            {
+            	if(wr->status == HEXB_STAT_WAITING) 
+            		busy_times++;
+            	auto_times++;
+              mutex_lock (&info->lock);
+              if(auto_times > HEXB_USB_TIMING_AUTO) {
+              	//Not an error some debug stuff
+              	//applog (LOG_ERR , "From %i us", (int)info->usb_timing); 
+              	a_count++;
+              	a_val = HEXB_USB_TIMING_AJUST / a_count;
+              	err_rate  = busy_times  / auto_times * 100;
+              	if(a_val<HEXB_USB_TIMING_AJUST_LOW_RES) a_val = HEXB_USB_TIMING_AJUST_LOW_RES;
+              	if (err_rate > HEXB_USB_TIMING_TARGET) {
+    							if (err_rate > 0.5) {
+    								//Be aggressive
+    								info->usb_timing+=800;
+    							} else {
+    								info->usb_timing+= a_val;       	
+              		}
+              	} else {
+              		info->usb_timing-= a_val;
+              	}
+              	//Not an error some debug stuff
+              	//applog (LOG_ERR , "To %i us err %f%%", (int)info->usb_timing, err_rate); 
+              	busy_times = 0;
+              	auto_times = 0;
+              }
+              info->wr_status = wr->status;
+              mutex_unlock (&info->lock);
+            }
+          else
+            {
+              goto out;
+            }
+          if (wr->address != HEXB_WORKANSWER_ADR)
+            goto out;
+          if(wr->lastnonceid > HEXMINERB_ARRAY_SIZE_REAL || wr->prevnonceid > HEXMINERB_ARRAY_SIZE_REAL) {
+					need_work_reset++;
+					if (wr->lastnonceid > HEXMINERB_ARRAY_SIZE_REAL )
+            wr->lastnonceid = 0;
+            
+					if (wr->prevnonceid > HEXMINERB_ARRAY_SIZE_REAL )
+            wr->prevnonceid = 0;
+          } else {
+          	need_work_reset = 0;
+          }
+          if(need_work_reset > HEXB_USB_R_BAD_ID) {
+          	  mutex_lock (&info->lock);
+              info->reset_work = true;
+              info->dev_reset_count++;
+              mutex_unlock (&info->lock);
+              goto out;
+          }  
+          if (wr->lastchippos > 15)
+            wr->lastchippos = 15;
+          found = 0;
+          if (libhexb_cachenonce
+              (&array_nonce_cache[wr->lastchippos], wr->lastnonce))
+            {
+              nonce = decnonce (htole32(wr->lastnonce));
+              found+=hexminerb_predecode_nonce (hexminerb, thr, nonce,
+                                           wr->prevnonceid);
+              found+=hexminerb_predecode_nonce (hexminerb, thr, nonce,
+                                             wr->lastnonceid);
+                                             
+              if (found>0)
+                {
+                  mutex_lock (&info->lock);
+                 
+                  if(info->nonces == 0) libhexb_getvoltage (htole16 (wr->lastvoltage),
+                                        &info->pic_voltage_readings);
+                  info->nonces+=found;
+                  info->matching_work[wr->lastchippos]++;
+                  mutex_unlock (&info->lock);
+                }
+              else
+                {
+                	//Due to implementation there is no way for now to count them. 
+                	//The number is inaccurate and too big!
+   
+                  //inc_hw_errors (thr);
+                }
+            }
+          else
+            {
+              mutex_lock (&info->lock);
+              info->dupe[wr->lastchippos]++;
+              mutex_unlock (&info->lock);
+            }
+        out:
+          if (ret_r == 2)
+            {
+              mutex_lock (&info->lock);
+              info->usb_r_errors++;
+              mutex_unlock (&info->lock);
+            }
+            //More nonces 
+        if (hash_write_pos - hash_read_pos > HEXB_MAX_WORK_SIZE)
+        	 goto again;
+        }
+      ret_r =
+        libhexb_readHashData (hexminerb, readbuf, &hash_write_pos, HEXMINERB_BULK_READ_TIMEOUT, true);
+        
+      if (ret_r != LIBUSB_SUCCESS)
+        {
+          usb_r_reset++;
+        	if(usb_r_reset > HEXB_USB_RES_THRESH) {
+          	libhexb_reset (hexminerb);
+      				usb_r_reset = 0;
+        	}
+          
+        } else {
+           usb_r_reset = 0;  
+        }
+        
+     //  if(libhexb_usb_dead(hexminerb)) break;
+     cgsleep_us_r (&ts_start, HEXMINERB_READ_TIMEOUT);
+    }
+  
+  free (wr);
+  free (array_nonce_cache);
+  pthread_exit (NULL);
+}
+
+static bool
+hexminerb_prepare (struct thr_info *thr)
+{
+  struct cgpu_info *hexminerb = thr->cgpu;
+  struct hexminerb_info *info = hexminerb->device_data;
+  
+  info->thr = thr;
+  mutex_init (&info->lock);
+  cgsem_init(&info->qsem);
+  
+  if (pthread_create
+      (&info->write_thr, NULL, hexminerb_send_tasks, (void *) hexminerb))
+    quit (1, "Failed to create hexminerb write_thr");
+  if (pthread_create
+      (&info->read_thr, NULL, hexminerb_get_results, (void *) hexminerb))
+    quit (1, "Failed to create hexminerb read_thr");
+  return true;
+}
+
+static int64_t
+hexminerb_scanhash (struct thr_info *thr)
+{
+    struct cgpu_info *hexminerb = thr->cgpu;
+    struct hexminerb_info *info = hexminerb->device_data;
+    struct work *work = NULL;
+    int64_t ms_timeout;
+    int64_t hash_count = 0;
+    /* 200 ms */
+    if(thr->work_restart) goto res;
+    ms_timeout = 200;
+    mutex_lock (&info->lock);
+    /* Rotate buffer */
+    if (info->read_pos >= HEXMINERB_ARRAY_SIZE_REAL
+        && info->write_pos >= HEXMINERB_ARRAY_SIZE_REAL ) {
+        info->write_pos = 0;
+        info->read_pos = 0;
+        info->cg_queue_cached_works = 0;
+    }
+    while(!(info->cg_queue_cached_works > HEXMINERB_PUSH_THRESH ||
+            info->write_pos >= HEXMINERB_ARRAY_SIZE_REAL)) {
+        mutex_unlock (&info->lock);
+        work = get_work(thr, thr->id);
+        mutex_lock (&info->lock);
+        if (work == NULL) break;
+        work->subid = info->write_pos;
+        if(info->hexworks[info->write_pos]!=NULL) free_work(info->hexworks[info->write_pos]);
+        info->hexworks[info->write_pos++] = work;
+        info->cg_queue_cached_works++;
+    }
+    hash_count = 0xffffffffull * (uint64_t) info->nonces;
+    info->nonces = 0;
+    mutex_unlock (&info->lock);
+    cgsem_mswait(&info->qsem, ms_timeout);
+res:
+    if (libhexb_usb_dead(hexminerb)) {
+        if(!hexminerb->shutdown) hexminerb->shutdown = true;
+        return -1;
+    }
+    if(thr->work_restart) {
+        mutex_lock (&info->lock);
+        info->reset_work = true;
+        /* Eat Buffer */
+        info->read_pos = 0;
+        info->write_pos = 0;
+        //Shall we get work here? All other drivers quit because it becomes stale or?
+        info->cg_queue_cached_works = 0;
+        mutex_unlock (&info->lock);
+    }
+    return hash_count;
+}
+
+static void
+get_hexminerb_statline_before (char *buf, size_t bufsiz,
+                               struct cgpu_info *hexminerb)
+{
+  //if (libhexb_usb_dead(hexminerb)) tailsprintf(buf, bufsiz, "               | ");
+  struct hexminerb_info *info = hexminerb->device_data;
+  tailsprintf (buf, bufsiz, "%3d %4d/%4dmV | ", info->frequency,
+               info->core_voltage, info->pic_voltage_readings);
+}
+
+static struct api_data *
+hexminerb_api_stats (struct cgpu_info *cgpu)
+{
+	
+  struct api_data *root = NULL;
+  struct hexminerb_info *info = cgpu->device_data;
+  uint64_t dh64, dr64;
+  double dev_runtime;
+  struct timeval now;
+  int i;
+  char displayed_hashes[16], displayed_rolling[16];
+  double hwp =
+    (cgpu->hw_errors +
+     cgpu->diff1) ? (double) (cgpu->hw_errors) / (double) (cgpu->hw_errors +
+                                                           cgpu->diff1) : 0;
+  if (cgpu->dev_start_tv.tv_sec == 0)
+    dev_runtime = total_secs;
+  else
+    {
+      cgtime (&now);
+      dev_runtime = tdiff (&now, &(cgpu->dev_start_tv));
+    }
+  if (dev_runtime < 1.0)
+    dev_runtime = 1.0;
+  dh64 = (double) cgpu->total_mhashes / dev_runtime * 1000000ull;
+  dr64 = (double) cgpu->rolling * 1000000ull;
+  suffix_string (dh64, displayed_hashes, sizeof (displayed_hashes), 4);
+  suffix_string (dr64, displayed_rolling, sizeof (displayed_rolling), 4);
+  root = api_add_string (root, "MHS 5s", displayed_rolling, true);
+  root = api_add_string (root, "MHS av", displayed_hashes, true);
+  root = api_add_int (root, "Hardware Errors", &(cgpu->hw_errors), false);
+  root = api_add_percent (root, "Hardware Errors%", &hwp, true);
+  root = api_add_int (root, "USB Read Errors", &(info->usb_r_errors), false);
+  root = api_add_int (root, "USB Write Errors", &(info->usb_w_errors), false);
+  root = api_add_int (root, "Idled for 60 sec", &(info->idled), false);
+  root = api_add_int (root, "Reset Count", &(info->dev_reset_count), false);
+  root =
+    api_add_time (root, "Last Share Time", &(cgpu->last_share_pool_time),
+                  false);
+  root = api_add_int (root, "Chip Count", &(info->asic_count), false);
+  root = api_add_int (root, "Frequency", &(info->frequency), false);
+  root = api_add_int (root, "Core Voltage", &(info->core_voltage), false);
+  root =
+    api_add_int (root, "PIC Voltage Readings", &(info->pic_voltage_readings),
+                 false);
+  for (i = 0; i < info->asic_count; i++)
+    {
+      char mcw[24];
+      sprintf (mcw, "Chip%d Nonces", i + 1);
+      root = api_add_int (root, mcw, &(info->matching_work[i]), false);
+      sprintf (mcw, "Chip%d Dupes", i + 1);
+      root = api_add_int (root, mcw, &(info->dupe[i]), false);
+    }
+  return root;
+}
+
+static bool hexminerb_thread_init(struct thr_info *thr)
+{
+	struct cgpu_info *hexminerb = thr->cgpu;
+	unsigned int wait;
+
+	/* Pause each new thread at least 100ms between initialising
+	 * so the devices aren't making calls all at the same time. */
+	wait = thr->id * HEXB_MAX_START_DELAY_MS;
+//	applog(LOG_DEBUG, "%s%d: Delaying start by %dms",
+	//		hexminerb->drv->name, hexminerb->device_id, wait / 1000);
+	cgsleep_ms(wait);
+
+	return true;
+}
+
+struct device_drv hexminerb_drv = {
+  .drv_id = DRIVER_hexminerb,
+  .dname = "hexminerb",
+  .name = "HEXb",
+  .drv_detect = hexminerb_detect,
+  .thread_prepare = hexminerb_prepare,
+  //.thread_init = hexminerb_thread_init,
+  .hash_work = hash_queued_work,
+  .scanwork = hexminerb_scanhash,
+  .flush_work = hexminerb_flush_work,
+  .get_api_stats = hexminerb_api_stats,
+  .get_statline_before = get_hexminerb_statline_before,
+  .thread_shutdown = hexminerb_shutdown,
+};
--- cg_o/driver-hexminerb.h	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/driver-hexminerb.h	2013-11-26 09:34:57.144117643 +0200
@@ -0,0 +1,146 @@
+/*$T indentinput.h GC 1.140 10/16/13 10:20:01 */
+/*
+ * Copyright 2013 Avalon project Copyright 2013 Con Kolivas <kernel@kolivas.org>
+ * 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. Thank you guy
+ */
+#ifndef HEXB_H
+#define HEXB_H
+#ifdef USE_HEXMINERB
+#include "util.h"
+/* hexminerb_task/work_reply status Definitions: */
+#define HEXB_STAT_IDLE					0       /* Idle or data already Sent to the buffer */
+#define HEXB_STAT_NEW_WORK				6       /* Request for write in the buffer */
+#define HEXB_STAT_WAITING				2       /* Wait For Buffer Empty Position */
+#define HEXB_STAT_CLR_BUFF				3       /* Force Buffer Empty */
+#define HEXB_STAT_STOP_REQ				4       /* Stop Request */
+#define HEXB_STAT_NEW_WORK_CLEAR_OLD		5       /* Clear Buffers and after that fill the first buffer */
+#define HEXB_STAT_UNUSED					7
+#define HEXMINERB_ARRAY_PIC_SIZE		64
+#define HEXMINERB_ARRAY_SIZE                  HEXMINERB_ARRAY_PIC_SIZE * 4 
+#define HEXMINERB_ARRAY_SIZE_REAL	HEXMINERB_ARRAY_SIZE - 2
+//#define HEXMINERB_ARRAY_SIZE 253
+#define HEXB_NONCE_CASH_SIZE				12
+#define HEXMINERB_PUSH_THRESH		8       /* At least 2 queued works available to be written to PIC */
+#define HEXMINERB_ARRAY_MAX_POP		1
+#define HEXB_USB_R_SIZE					64
+#define HEXB_USB_WR_SIZE					64
+#define HEXB_HASH_BUF_SIZE				2048*4
+#define HEXB_USB_TIMING						50 * 1000
+#define HEXB_USB_R_BAD_ID					32
+//How often
+//About two mins
+#define HEXB_USB_TIMING_AUTO			6000
+#define HEXB_USB_TIMING_TARGET    0.0015
+//6ms
+#define HEXB_USB_TIMING_AJUST			1800
+#define HEXB_USB_TIMING_AJUST_LOW_RES			20
+#define HEXB_USB_WR_TIME_OUT				0
+#define HEXMINERB_READ_TIMEOUT		1000 * 5
+#define HEXMINERB_BULK_READ_TIMEOUT 0
+#define HEXB_USB_RES_THRESH				400 //About 2 sec with consecutive failed reads
+#define HEXB_MAX_START_DELAY_MS		1000
+#define HEXB_MINER_THREADS			1
+#define HEXB_DEFAULT_MINER_NUM		0x01
+#define HEXB_DEFAULT_ASIC_NUM		0x10
+#define HEXB_MIN_FREQUENCY			0       //Bits / 10
+#define HEXB_MAX_FREQUENCY			610     //Bits / 10
+#define HEXB_DEFAULT_FREQUENCY		540     //Bits / 10 - That is Max which works 40 GHs for 16 chips
+#define HEXB_DEFAULT_CORE_VOLTAGE	840     /* in millivolts */
+#define HEXB_MIN_COREMV				700     /* in millivolts */
+#define HEXB_MAX_COREMV	1101     /* in millivolts */
+struct chip_resultsb
+{
+  uint8_t nonce_cache_write_pos;
+  uint32_t nonces[HEXB_NONCE_CASH_SIZE];
+};
+struct workb_result
+{
+  uint8_t startbyte;
+  uint8_t datalength;
+  uint8_t command;
+  uint16_t address;
+  uint32_t lastnonce;
+  uint8_t lastnonceid;
+  uint8_t status;
+  uint16_t lastvoltage;
+  uint8_t lastchippos;          //Old position of uint16_t LastTemperature;
+  uint8_t prevnonceid;
+  uint16_t lastfanrpm;
+  uint32_t serial;
+  uint16_t openloadduty;
+  uint16_t workingduty;
+  uint16_t lastworkingduty;
+  uint16_t clockforce;          /* Times Avalons Crashed */
+  uint8_t pad[3];
+} __attribute__ ((packed, aligned (4)));
+struct hexminerb_info
+{
+  int miner_count;
+  int asic_count;
+  int core_voltage;
+  int frequency;
+  int idled;
+  int nonces;
+  int read_pos;
+  int write_pos;
+  int usb_r_errors;
+  int usb_w_errors;
+  int dev_reset_count;
+  int pic_voltage_readings;
+  int64_t usb_timing;
+  int cg_queue_cached_works;
+  int dupe[HEXB_DEFAULT_ASIC_NUM];
+  int matching_work[HEXB_DEFAULT_ASIC_NUM];
+  bool reset_work;
+  bool start_up;
+  uint8_t wr_status;
+  uint8_t wr_lastnonceid;
+  pthread_t read_thr;
+  pthread_t write_thr;
+  pthread_mutex_t lock;
+  cgsem_t qsem;
+  struct thr_info *thr;
+  struct work **hexworks;
+};
+/*
+ -----------------------------------------------------------------------------------------------------------------------
+    2 + 3 + 1 + 1 + 1 + 1 + 1 + 8 + 1 + 1 + 1 + 2 = 23(uint32_t)=46(uint16_t)=
+ -----------------------------------------------------------------------------------------------------------------------
+ */
+struct hexminerb_task
+{
+  uint32_t merkle[3];
+  uint32_t a1;                  //midstate3[0]
+  uint32_t a0;                  //midstate3[1]
+  uint32_t e2;                  //midstate3[2]
+  uint32_t e1;                  //midstate3[3]
+  uint32_t e0;                  //midstate3[4]
+  uint8_t midstate[32];
+  uint32_t a2;                  //midstate3[5]
+  uint32_t startnonce;          //midstate3[6]
+  uint8_t id;
+  uint8_t status;
+  uint16_t hashclock;
+  uint16_t chipcount;
+  uint16_t refvoltage;
+  uint16_t reftemperature;      //midstate3[7]
+  uint16_t reffanrpm;           //midstate3[7]
+} __attribute__ ((packed, aligned (4)));
+#define HEXB_WORKANSWER_ADR	0x3000
+#define HEXB_WORKQUEUE_ADR	0x4008
+#define HEXB_PTCON_ADR		0x0C00
+#define HEXB_START_STOP_ADR	0x646E
+#define HEXMINERB_TASK_SIZE	(sizeof(struct hexminerb_task))
+#define HEXB_MAX_WORK_SIZE		(sizeof(struct workb_result) - 3)
+#define HEXB_BASE_WORK_SIZE		6       /* Min uint8_t startbyte + uint8_t datalength + uint8_t command + uint16_t
+                                                 * address;
+                                                 * + uint8_t csum */
+extern int opt_hexminerb_core_voltage;
+extern char *libhexb_set_config_voltage (char *arg);
+extern struct hexminerb_info **hexminerb_info;
+#endif /* USE_HEXMINERB */
+#endif /* HEXB_H */
--- cg_o/libhexb.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/libhexb.c	2013-11-26 09:34:57.144117643 +0200
@@ -0,0 +1,405 @@
+/*$T indentinput.c GC 1.140 10/16/13 10:20:34 */
+const uint32_t SHA_M[64] = {
+  0x428a2f98, 0x71374491, 0xb5c0fbcf
+};
+
+#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
+#define Maj(x, y, z) ((x & (y | z)) | (y & z))
+#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
+#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+//0x2800000, 0x2C00000, 0x400000 - CPU wasteed No valid results for the moment
+#define BT_OFFSETS_B 3
+const uint32_t bf_offsetsb[] =
+  { -0x800000, 0, -0x400000, 0x2800000, 0x2C00000, 0x400000 };
+
+static void
+BITFURY_MS3compute (struct work *work, struct hexminerb_task *ht)
+{
+  uint32_t state[8];
+  uint32_t data[3];
+  memcpy (&state, work->midstate, 32);
+  memcpy (&data, work->data + 64, 12);
+  uint32_t a, b, c, d, e, f, g, h, ne, na;
+  int i;
+#if defined(__BIG_ENDIAN__) || defined(MIPSEB)
+  for (i = 0; i < 8; i++)
+    state[i] = htole32 (state[i]);
+  for (i = 0; i < 3; i++)
+    data[i] = htole32 (data[i]);
+#endif
+  a = state[0];
+  b = state[1];
+  c = state[2];
+  d = state[3];
+  e = state[4];
+  f = state[5];
+  g = state[6];
+  h = state[7];
+  for (i = 0; i < 3; i++)
+    {
+      ne = data[i] + SHA_M[i] + h + Ch (e, f, g) + S1 (e) + d;
+      na = data[i] + SHA_M[i] + h + Ch (e, f, g) + S1 (e) + S0 (a) +
+        Maj (a, b, c);
+      d = c;
+      c = b;
+      b = a;
+      a = na;
+      h = g;
+      g = f;
+      f = e;
+      e = ne;
+    }
+#if defined(__BIG_ENDIAN__) || defined(MIPSEB)
+  a = htole32 (a);
+  b = htole32 (b);
+  c = htole32 (c);
+  d = htole32 (d);
+  e = htole32 (e);
+  f = htole32 (f);
+  g = htole32 (g);
+  h = htole32 (h);
+#endif
+  memcpy (&ht->a1, &h, 4);
+  memcpy (&ht->a0, &g, 4);
+  memcpy (&ht->e2, &f, 4);
+  memcpy (&ht->e1, &e, 4);
+  memcpy (&ht->e0, &d, 4);
+  memcpy (&ht->a2, &c, 4);
+  memcpy (&ht->startnonce, &b, 4);
+  memcpy (&ht->reftemperature, &a, 4);
+}
+
+static bool
+libhexb_cachenonce (struct chip_resultsb *nonce_cache, uint32_t nonce)
+{
+  int i = 0;
+  while (i < HEXB_NONCE_CASH_SIZE && nonce_cache->nonces[i] != nonce)
+    i++;
+  if (i < HEXB_NONCE_CASH_SIZE)
+    return false;
+  //Rotate
+  if (nonce_cache->nonce_cache_write_pos == HEXB_NONCE_CASH_SIZE)
+    nonce_cache->nonce_cache_write_pos = 0;
+  nonce_cache->nonces[nonce_cache->nonce_cache_write_pos++] = nonce;
+  return true;
+}
+
+char *
+libhexb_set_config_voltage (char *arg)
+{
+  int val1, ret;
+  ret = sscanf (arg, "%d", &val1);
+  if (ret < 1)
+    return "No values passed to hexminerb-voltage";
+  if (val1 < HEXB_MIN_COREMV || val1 > HEXB_MAX_COREMV)
+    return "Invalid value passed to hexminerb-voltage";
+  opt_hexminerb_core_voltage = val1;
+  return NULL;
+}
+
+static void
+libhexb_csum (unsigned char *startptr, unsigned char *endptr,
+              unsigned char *resptr)
+{
+  unsigned char *b = startptr;
+  uint8_t sum = 0;
+  while (b < endptr)
+    sum += *b++;
+  memcpy (resptr, &sum, 1);
+}
+
+static bool
+libhexb_get_options (int this_option_offset, int *asic_count, int *frequency)
+{
+  char buf[BUFSIZ + 1];
+  char *ptr, *comma, *colon, *colon2, *colon3, *colon4;
+  bool timeout_default;
+  size_t max;
+  int i, tmp;
+
+  if (opt_hexminerb_options == NULL)
+    buf[0] = '\0';
+  else
+    {
+      ptr = opt_hexminerb_options;
+      for (i = 0; i < this_option_offset; i++)
+        {
+          comma = strchr (ptr, ',');
+          if (comma == NULL)
+            break;
+          ptr = comma + 1;
+        }
+      comma = strchr (ptr, ',');
+      if (comma == NULL)
+        max = strlen (ptr);
+      else
+        max = comma - ptr;
+      if (max > BUFSIZ)
+        max = BUFSIZ;
+      strncpy (buf, ptr, max);
+      buf[max] = '\0';
+    }
+  if (!(*buf))
+    return false;
+  colon = strchr (buf, ':');
+  if (colon)
+    *(colon++) = '\0';
+  tmp = atoi (buf);
+  if (tmp > 0 && tmp <= HEXB_DEFAULT_ASIC_NUM)
+    *asic_count = tmp;
+  else
+    {
+      quit (1,
+            "Invalid hexminerb-options for " "asic_count (%s) must be 1 ~ %d",
+            buf, HEXB_DEFAULT_ASIC_NUM);
+    }
+  if (colon && *colon)
+    {
+      tmp = atoi (colon);
+      if (tmp < HEXB_MIN_FREQUENCY || tmp > HEXB_MAX_FREQUENCY)
+        {
+          quit
+            (1,
+             "Invalid hexminerb-options for frequency (%s) must be %d <= frequency <= %d",
+             colon, HEXB_MIN_FREQUENCY, HEXB_MAX_FREQUENCY);
+        }
+      *frequency = tmp;
+    }
+  return true;
+}
+
+static bool
+libhexb_usb_dead (struct cgpu_info *hexminerb)
+{
+  struct cg_usb_device *usbdev;
+  usbdev = hexminerb->usbdev;
+  return (usbdev == NULL
+          || usbdev->handle == NULL
+          || hexminerb->shutdown
+          || hexminerb->usbinfo.nodev || hexminerb->deven != DEV_ENABLED);
+}
+
+static int
+libhexb_sendHashData (struct cgpu_info *hexminerb, unsigned char *sendbuf,
+                      size_t buf_len)
+{
+  struct hexminerb_info *info = hexminerb->device_data;
+  struct cg_usb_device *usbdev;
+  int wrote = 0, written = 0;
+  int err = LIBUSB_SUCCESS;
+  int pstate;
+  usb_lock_w (hexminerb, pstate);
+  usbdev = hexminerb->usbdev;
+  if (libhexb_usb_dead (hexminerb))
+    goto out;
+  while (written < buf_len && err == LIBUSB_SUCCESS)
+    {
+      err = libusb_bulk_transfer
+        (usbdev->handle,
+         0x02,
+         sendbuf + written,
+         MIN (HEXB_USB_WR_SIZE, buf_len - written), &wrote,
+         HEXB_USB_WR_TIME_OUT);
+      if (err == LIBUSB_SUCCESS)
+        written += wrote;
+    }
+out:
+  usb_unlock_w (hexminerb, pstate);
+  return written;
+}
+
+static void
+libhexb_reset (struct cgpu_info *hexminerb)
+{
+  struct hexminerb_info *info = hexminerb->device_data;
+  struct cg_usb_device *usbdev;
+  int err = LIBUSB_SUCCESS;
+  int pstate;
+  usb_lock_w (hexminerb, pstate);
+  usbdev = hexminerb->usbdev;
+  if (libhexb_usb_dead (hexminerb))
+    goto out;
+  err = libusb_reset_device (usbdev->handle);
+out:
+  usb_unlock_w (hexminerb, pstate);
+}
+
+static int libhexb_readHashData
+  (struct cgpu_info *hexminerb,
+   unsigned char *hash, int *hash_write_pos, int timeout, bool read_once)
+{
+  struct hexminerb_info *info = hexminerb->device_data;
+  struct cg_usb_device *usbdev;
+  int read = 0, total = 0;
+  int err = LIBUSB_SUCCESS;
+  int pstate;
+  usb_lock_r (hexminerb, pstate);
+  usbdev = hexminerb->usbdev;
+  if (libhexb_usb_dead (hexminerb))
+    goto out;
+  while (*hash_write_pos + HEXB_USB_R_SIZE < HEXB_HASH_BUF_SIZE
+         && err == LIBUSB_SUCCESS)
+    {
+      err =
+        libusb_bulk_transfer (usbdev->handle, 0x82, hash + *hash_write_pos,
+                              HEXB_USB_R_SIZE, &read, timeout);
+      if (err == LIBUSB_SUCCESS)
+        {
+          *hash_write_pos += read;
+          total += read;
+        }
+      if (read_once)
+        break;
+    }
+
+out:
+  usb_unlock_r (hexminerb, pstate);
+
+  if (err == LIBUSB_ERROR_NO_DEVICE || err == LIBUSB_ERROR_NOT_FOUND)
+    {
+
+      hexminerb->shutdown = true;
+      cgsem_post (&info->qsem);
+    }
+
+  return err;
+}
+
+static uint32_t
+decnonce (uint32_t in)
+{
+  uint32_t out;
+  /* First part load */
+  out = (in & 0xFF) << 24;
+  in >>= 8;
+  /* Byte reversal */
+  in = (((in & 0xaaaaaaaa) >> 1) | ((in & 0x55555555) << 1));
+  in = (((in & 0xcccccccc) >> 2) | ((in & 0x33333333) << 2));
+  in = (((in & 0xf0f0f0f0) >> 4) | ((in & 0x0f0f0f0f) << 4));
+  out |= (in >> 2) & 0x3FFFFF;
+  /* Extraction */
+  if (in & 1)
+    out |= (1 << 23);
+  if (in & 2)
+    out |= (1 << 22);
+  out -= 0x800004;
+  return out;
+}
+
+static int
+bitfury_checkresults (struct thr_info *thr, struct work *work, uint32_t nonce)
+{
+  int i;
+  for (i = 0; i < BT_OFFSETS_B; i++)
+    {
+      if (test_nonce (work, nonce + bf_offsetsb[i]))
+        {
+
+          submit_tested_work (thr, work);
+          return 1;
+        }
+    }
+  return 0;
+}
+
+static int
+hexminerb_predecode_nonce (struct cgpu_info *hexminerb, struct thr_info *thr,
+                           uint32_t nonce, uint8_t work_id)
+{
+  struct hexminerb_info *info = hexminerb->device_data;
+  int res = 0;
+
+  mutex_lock (&info->lock);
+  if (info->hexworks[work_id] == NULL)
+    goto out;
+
+  res = bitfury_checkresults (thr, info->hexworks[work_id], nonce);
+
+out:
+  mutex_unlock (&info->lock);
+
+  return res;
+}
+
+static void
+libhexb_getvoltage (uint16_t wr_bukvoltage, int *info_pic_voltage_readings)
+{
+  float voltagehuman;
+  voltagehuman =
+    (float) ((float) wr_bukvoltage * (float) 1000 * (float) 3.3 /
+             ((1 << 12) - 1));
+  *info_pic_voltage_readings = (int) voltagehuman;
+}
+
+static void
+libhexb_setvoltage (int info_voltage, uint16_t * refvoltage)
+{
+  uint16_t voltageadc;
+  voltageadc =
+    (uint16_t) ((float) info_voltage / (float) 1000 / (float) 3.3 *
+                ((1 << 12) - 1));
+  *refvoltage = htole16 (voltageadc);
+}
+
+static int
+libhexb_eatHashData (struct workb_result *wr, unsigned char *hash,
+                     int *hash_read_pos, int *hash_write_pos)
+{
+  uint8_t psum;
+  int wrpos;
+  unsigned char *csum_pos;
+  bool ok;
+eat:
+  while (*hash_read_pos < *hash_write_pos && hash[*hash_read_pos] != 0x53)
+    {
+      *hash_read_pos += 1;
+    }
+  if (*hash_write_pos - *hash_read_pos < HEXB_BASE_WORK_SIZE)
+    goto done;
+  memcpy ((char *) &wr->startbyte, &hash[*hash_read_pos],
+          HEXB_BASE_WORK_SIZE - 1);
+  wr->address = htole16 (wr->address);
+
+  /* Address is outside be strict to avoid mem corruption - not fancy but it works */
+
+  ok = (wr->command == 0x52) &&
+    ((wr->address == HEXB_WORKANSWER_ADR && wr->datalength == 0x05)
+     || (wr->address == HEXB_WORKANSWER_ADR + 4 && wr->datalength == 1));
+  if (!ok)
+    {
+      *hash_read_pos += 1;
+      goto eat;
+    }
+  if (*hash_write_pos - *hash_read_pos <
+      HEXB_BASE_WORK_SIZE + wr->datalength * 2)
+    goto done;
+  csum_pos =
+    hash + *hash_read_pos + HEXB_BASE_WORK_SIZE + wr->datalength * 2 - 1;
+  //Crap?
+  if (csum_pos - hash < HEXB_HASH_BUF_SIZE)
+    {
+//That was writing somewhere and corrupting memory because of faulty usb reads....
+      libhexb_csum (hash + *hash_read_pos, csum_pos, &psum);
+      if (psum != *csum_pos)
+        {
+          *hash_read_pos += 1;
+          return 2;
+        }
+    }
+  else
+    {
+      *hash_read_pos += 1;
+      return 2;
+    }
+  wrpos = (wr->address - HEXB_WORKANSWER_ADR) + HEXB_BASE_WORK_SIZE - 1;
+  memcpy
+    ((char *) &wr->startbyte + wrpos,
+     &hash[*hash_read_pos + HEXB_BASE_WORK_SIZE - 1],
+     MIN (wr->datalength * 2, HEXB_MAX_WORK_SIZE - HEXB_BASE_WORK_SIZE - 1));
+  *hash_read_pos += HEXB_BASE_WORK_SIZE + wr->datalength * 2;
+  return 1;
+done:
+  return 0;
+}
+ 
\ No newline at end of file
--- cg_o/Makefile.am	2013-11-26 09:34:42.939360228 +0200
+++ cgminer/Makefile.am	2013-11-26 09:34:57.144117643 +0200
@@ -88,6 +88,22 @@
 cgminer_SOURCES += driver-bab.c
 endif
 
+if HAS_HEXMINERA
+cgminer_SOURCES += driver-hexminera.c driver-hexminera.h
+endif
+
+if HAS_HEXMINERB
+cgminer_SOURCES += driver-hexminerb.c driver-hexminerb.h
+endif
+
+if HAS_HEXMINERC
+cgminer_SOURCES += driver-hexminerc.c driver-hexminerc.h
+endif
+
+if HAS_HEXMINERN
+cgminer_SOURCES += driver-hexminern.c driver-hexminern.h
+endif
+
 if HAS_MODMINER
 cgminer_SOURCES += driver-modminer.c
 bitstreamsdir = $(bindir)/bitstreams
--- cg_o/miner.h	2013-11-26 09:34:42.939360228 +0200
+++ cgminer/miner.h	2013-11-26 09:34:57.144117643 +0200
@@ -236,6 +236,10 @@
 	DRIVER_ADD_COMMAND(modminer)
 
 #define ASIC_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	DRIVER_ADD_COMMAND(hexminera) \
+	DRIVER_ADD_COMMAND(hexminerb) \
+	DRIVER_ADD_COMMAND(hexminerc) \
+	DRIVER_ADD_COMMAND(hexminern) \
 	DRIVER_ADD_COMMAND(bflsc) \
 	DRIVER_ADD_COMMAND(bitfury) \
 	DRIVER_ADD_COMMAND(hashfast) \
@@ -276,6 +280,15 @@
 	POOL_LOADBALANCE,
 	POOL_BALANCE,
 };
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC)
+
+enum default_hex_miner {
+	D_HEXA,
+	D_HEXB,
+	D_HEXC,
+};
+extern enum default_hex_miner default_hex_miner;
+#endif
 
 #define TOP_STRATEGY (POOL_BALANCE)
 
@@ -475,6 +488,7 @@
 	int queued;
 	int results;
 #endif
+
 #ifdef USE_USBUTILS
 	struct cg_usb_info usbinfo;
 #endif
@@ -1005,6 +1019,18 @@
 #ifdef USE_KLONDIKE
 extern char *opt_klondike_options;
 #endif
+#ifdef USE_HEXMINERA
+extern char *opt_hexminera_options;
+#endif
+#ifdef USE_HEXMINERB
+extern char *opt_hexminerb_options;
+#endif
+#ifdef USE_HEXMINERC
+extern char *opt_hexminerc_options;
+#endif
+#ifdef USE_HEXMINERN
+extern char *opt_hexminern_options;
+#endif
 #ifdef USE_USBUTILS
 extern char *opt_usb_select;
 extern int opt_usbdump;
--- cg_o/usbutils.c	2013-11-26 09:34:42.939360228 +0200
+++ cgminer/usbutils.c	2013-11-26 12:18:32.349168576 +0200
@@ -217,6 +217,42 @@
 };
 #endif
 
+#ifdef USE_HEXMINERA
+static struct usb_epinfo hexa_epinfos[] = {
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPI(2), 0, 0 },
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPO(2), 0, 0 }
+};
+static struct usb_intinfo hexa_ints[] = {
+	USB_EPS(1, hexa_epinfos)
+};
+#endif
+#ifdef USE_HEXMINERB
+static struct usb_epinfo hexb_epinfos[] = {
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPI(2), 0, 0 },
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPO(2), 0, 0 }
+};
+static struct usb_intinfo hexb_ints[] = {
+	USB_EPS(1, hexb_epinfos)
+};
+#endif
+#ifdef USE_HEXMINERC
+static struct usb_epinfo hexc_epinfos[] = {
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPI(2), 0, 0 },
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPO(2), 0, 0 }
+};
+static struct usb_intinfo hexc_ints[] = {
+	USB_EPS(1, hexc_epinfos)
+};
+#endif
+#ifdef USE_HEXMINERN
+static struct usb_epinfo hexn_epinfos[] = {
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPI(2), 0, 0 },
+	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPO(2), 0, 0 }
+};
+static struct usb_intinfo hexn_ints[] = {
+	USB_EPS(1, hexn_epinfos)
+};
+#endif
 #ifdef USE_ICARUS
 static struct usb_epinfo ica_epinfos[] = {
 	{ LIBUSB_TRANSFER_TYPE_BULK,	64,	EPI(3), 0, 0 },
@@ -359,6 +395,7 @@
 		.latency = LATENCY_UNUSED,
 		INTINFO(mmq_ints) },
 #endif
+
 #ifdef USE_AVALON
 	{
 		.drv = DRIVER_avalon,
@@ -431,6 +468,68 @@
 		.latency = 10,
 		INTINFO(kli_ints) },
 #endif
+#ifdef USE_HEXMINERB //04d8:000a or //04d8:000b
+	{
+		.drv = DRIVER_hexminerb,
+		.name = "HEXb",
+		.ident = IDENT_HEXB,
+		.idVendor = 0x04D8,
+		.idProduct = 0x000B,
+		.iProduct = "HEX16B-Bitfury ASIC Miner",
+		.config = 1,
+		.timeout = 100,
+		.latency = LATENCY_UNUSED,
+		 INTINFO(hexb_ints) },
+	{	 
+		.drv = DRIVER_hexminerb,
+		.name = "HEXb",
+		.ident = IDENT_HEXB,
+		.idVendor = 0x04D8,
+		.idProduct = 0x000A,
+		.iProduct = "HEX16B-Bitfury ASIC Miner",
+		.config = 1,
+		.timeout = 100,
+		.latency = LATENCY_UNUSED,
+		 INTINFO(hexb_ints) },
+#endif
+#ifdef USE_HEXMINERC //04d8:000a
+	{
+		.drv = DRIVER_hexminerc,
+		.name = "HEXc",
+		.ident = IDENT_HEXC,
+		.idVendor = 0x04D8,
+		.idProduct = 0x000A,
+		.iProduct = "HEX16C-Avalon2 ASIC Miner",
+		.config = 1,
+		.timeout = 100,
+		.latency = LATENCY_UNUSED,
+		 INTINFO(hexc_ints) },
+#endif
+#ifdef USE_HEXMINERN //04d8:000a
+	{
+		.drv = DRIVER_hexminern,
+		.name = "HEXn",
+		.ident = IDENT_HEXN,
+		.idVendor = 0x04D8,
+		.idProduct = 0x00DE,
+		.config = 1,
+		.timeout = 100,
+		.latency = LATENCY_UNUSED,
+		 INTINFO(hexn_ints) },
+#endif
+#ifdef USE_HEXMINERA //04d8:000a
+	{
+		.drv = DRIVER_hexminera,
+		.name = "HEXa",
+		.ident = IDENT_HEXA,
+		.idVendor = 0x04D8,
+		.idProduct = 0x000A,
+		.iProduct = "HEX16A-Avalon1 ASIC Miner",
+		.config = 1,
+		.timeout = 100,
+		.latency = LATENCY_UNUSED,
+		 INTINFO(hexa_ints) },
+#endif 
 #ifdef USE_ICARUS
 	{
 		.drv = DRIVER_icarus,
@@ -805,7 +904,6 @@
 {
 	char tmp[512];
 	int err;
-
 	err = libusb_set_configuration(handle, cd);
 	if (err) {
 		snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Failed to set config descriptor to %d, err %d",
@@ -890,6 +988,7 @@
 	append(buf, tmp, off, len);
 
 	err = libusb_open(dev, &handle);
+	
 	if (err) {
 		snprintf(tmp, sizeof(tmp), EOL "  ** dev %d: Failed to open, err %d", (int)(*count), err);
 		append(buf, tmp, off, len);
@@ -1437,6 +1536,7 @@
 	}
 
 	_usb_uninit(cgpu);
+
 	cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address);
 }
 
@@ -1647,16 +1747,42 @@
 
 	if (found->iProduct) {
 		unsigned char prod[STRBUFLEN+1];
-
+    
 		err = libusb_get_string_descriptor_ascii(cgusb->handle,
 							 cgusb->descriptor->iProduct,
 							 prod, STRBUFLEN);
 		if (err < 0) {
+		
+			#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC)
+				bzero(prod,STRBUFLEN);
+			#if defined(USE_HEXMINERA)
+			if(found->ident == IDENT_HEXA && default_hex_miner == D_HEXA) {
+				strcpy(prod, "HEX16A-Avalon1 ASIC Miner");
+			} 
+			#endif
+			
+			#if defined(USE_HEXMINERB)
+			if(found->ident == IDENT_HEXB && default_hex_miner == D_HEXB) {
+				strcpy(prod, "HEX16B-Bitfury ASIC Miner");
+			} 
+			#endif
+			
+		  #if defined(USE_HEXMINERC)
+			if(found->ident == IDENT_HEXC && default_hex_miner == D_HEXC) {
+				strcpy(prod, "HEX16C-Avalon2 ASIC Miner");
+			} 
+			#endif
+
+			#else
+			
 			applog(LOG_DEBUG,
 				"USB init, failed to get iProduct, err %d %s",
 				err, devstr);
 			goto cldame;
+			#endif
+			
 		}
+		
 		if (strcmp((char *)prod, found->iProduct)) {
 			applog(LOG_DEBUG, "USB init, iProduct mismatch %s",
 			       devstr);
@@ -1783,11 +1909,26 @@
 
 	err = libusb_get_string_descriptor_ascii(cgusb->handle,
 				cgusb->descriptor->iProduct, strbuf, STRBUFLEN);
+	#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC)
+	  	if (err > 0)
+		cgusb->prod_string = strdup((char *)strbuf);
+	else {
+		#if defined(USE_HEXMINERA)
+		if(default_hex_miner == D_HEXA) cgusb->prod_string = strdup((char *)"HEX16A-Avalon1 ASIC Miner");
+		#endif
+		#if defined(USE_HEXMINERB)
+		if(default_hex_miner == D_HEXB) cgusb->prod_string = strdup((char *)"HEX16B-Bitfury ASIC Miner");
+		#endif
+		#if defined(USE_HEXMINERC)
+		if(default_hex_miner == D_HEXC) cgusb->prod_string = strdup((char *)"HEX16C-Avalon2 ASIC Miner");
+		#endif
+	}
+	#else
 	if (err > 0)
 		cgusb->prod_string = strdup((char *)strbuf);
 	else
 		cgusb->prod_string = (char *)BLANK;
-
+  #endif
 	err = libusb_get_string_descriptor_ascii(cgusb->handle,
 				cgusb->descriptor->iManufacturer, strbuf, STRBUFLEN);
 	if (err > 0)
@@ -2015,7 +2156,7 @@
 				drv->dname, drv_count[drv->drv_id].limit);
 			break;
 		}
-
+    
 		found = usb_check(drv, list[i]);
 		if (found != NULL) {
 			if (is_in_use(list[i]) || cgminer_usb_lock(drv, list[i]) == false)
@@ -2918,6 +3059,27 @@
 	return (ret & FTDI_RS0_CTS);
 }
 
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN)
+void usb_lock_w(struct cgpu_info *cgpu, int pstate) {
+  		DEVWLOCK(cgpu, pstate);
+}
+
+void usb_unlock_w(struct cgpu_info *cgpu, int pstate) {
+   
+  DEVWUNLOCK(cgpu, pstate); 
+}
+
+void usb_lock_r(struct cgpu_info *cgpu, int pstate) {
+  		DEVRLOCK(cgpu, pstate);
+}
+
+void usb_unlock_r(struct cgpu_info *cgpu, int pstate) {
+   
+  DEVRUNLOCK(cgpu, pstate); 
+}
+
+#endif
+
 int _usb_ftdi_set_latency(struct cgpu_info *cgpu, int intinfo)
 {
 	int err = 0;
@@ -3094,6 +3256,10 @@
 	for (i = 0; i < total_devices; i++) {
 		cgpu = devices[i];
 		switch (cgpu->drv->drv_id) {
+			case DRIVER_hexminera:
+			case DRIVER_hexminerb:
+			case DRIVER_hexminerc:
+			//case DRIVER_hexminern:
 			case DRIVER_bflsc:
 			case DRIVER_bitforce:
 			case DRIVER_bitfury:
--- cg_o/usbutils.h	2013-11-26 09:34:42.939360228 +0200
+++ cgminer/usbutils.h	2013-11-26 09:34:57.144117643 +0200
@@ -135,6 +135,10 @@
 enum sub_ident {
 	IDENT_UNK = 0,
 	IDENT_AMU,
+	IDENT_HEXA,
+	IDENT_HEXB,
+	IDENT_HEXC,
+	IDENT_HEXN,
 	IDENT_AVA,
 	IDENT_BAJ,
 	IDENT_BAL,
@@ -489,5 +493,5 @@
 
 #define usb_transfer_read(cgpu, typ, req, val, idx, buf, bufsiz, read, cmd) \
 	_usb_transfer_read(cgpu, typ, req, val, idx, buf, bufsiz, read, DEVTIMEOUT, cmd)
-
+	
 #endif
--- cg_o/api.c	2013-11-26 09:34:42.859355961 +0200
+++ cgminer/api.c	2013-11-26 09:34:57.148117824 +0200
@@ -25,7 +25,7 @@
 #include "miner.h"
 #include "util.h"
 
-#if defined(USE_BFLSC) || defined(USE_AVALON) || defined(USE_HASHFAST) || defined(USE_BITFURY) || defined(USE_KLONDIKE) || defined(USE_KNC) || defined(USE_BAB)
+#if defined(USE_HEXMINERA) || defined(USE_HEXMINERB) || defined(USE_HEXMINERC) || defined(USE_HEXMINERN) || defined(USE_BFLSC) || defined(USE_AVALON) || defined(USE_HASHFAST) || defined(USE_BITFURY) || defined(USE_KLONDIKE) || defined(USE_KNC) || defined(USE_BAB)
 #define HAVE_AN_ASIC 1
 #endif
 
@@ -168,6 +168,18 @@
 #ifdef USE_HASHFAST
 			"HFA "
 #endif
+#ifdef USE_HEXMINERA
+			"HEXa "
+#endif
+#ifdef USE_HEXMINERB
+			"HEXb "
+#endif
+#ifdef USE_HEXMINERC
+			"HEXc "
+#endif
+#ifdef USE_HEXMINERN
+			"HEXn "
+#endif
 #ifdef USE_ICARUS
 			"ICA "
 #endif
--- cg_o/driver-hexminera.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/driver-hexminera.c	2013-11-26 12:15:47.912275132 +0200
@@ -0,0 +1,529 @@
+/*$T indentinput.c GC 1.140 10/16/13 10:19:47 */
+/*
+ * Copyright 2013 Con Kolivas <kernel@kolivas.org> Copyright 2012-2013 Xiangfu
+ * <xiangfu@openmobilefree.com> Copyright 2012 Luke Dashjr Copyright 2012 Andrew
+ * Smith 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. Thank you guys!
+ */
+#include "config.h"
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <unistd.h>
+#ifndef WIN32
+#include <sys/select.h>
+#include <termios.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifndef O_CLOEXEC
+#define O_CLOEXEC	0
+#endif
+#else
+#include "compat.h"
+#include <windows.h>
+#include <io.h>
+#endif
+#include "elist.h"
+#include "miner.h"
+#include "usbutils.h"
+#include "driver-hexminera.h"
+#include "util.h"
+
+static int option_offset = -1;
+struct device_drv hexminera_drv;
+int opt_hexminera_core_voltage = HEXA_DEFAULT_CORE_VOLTAGE;
+#include "libhexa.c"
+
+static void
+hexminera_flush_work (struct cgpu_info *hexminera)
+{
+    struct hexminera_info *info = hexminera->device_data;
+    cgsem_post(&info->qsem);
+}
+
+static int
+hexminera_send_task (struct hexminera_task *ht, struct cgpu_info *hexminera)
+{
+    unsigned char buf[HEXMINERA_TASK_SIZE + 6];
+    int ret, amount = 0;
+    struct hexminera_info *info;
+    size_t nr_len = HEXMINERA_TASK_SIZE + 6;
+    uint16_t workqueue_adr = htole16 (HEXA_WORKQUEUE_ADR);
+    buf[0] = 0x53;
+    buf[2] = 0x57;                /* Write Command - char 'W' (0x57) */
+    info = hexminera->device_data;
+    libhexa_generateclk (info->frequency, HEXA_DEFAULT_XCLKIN_CLOCK,
+                         (uint32_t *) & ht->clockcfg[0]);
+    libhexa_setvoltage (info->core_voltage, &ht->refvoltage);
+    ht->chipcount = htole16 (info->asic_count);
+    ht->hashclock = htole16 ((uint16_t) info->frequency);
+    ht->startnonce = 0x00000000;
+    memcpy (buf + 5, ht, HEXMINERA_TASK_SIZE);
+    /* Count Words */
+    buf[1] = (uint8_t) ((HEXMINERA_TASK_SIZE) / 2);
+    memcpy (buf + 3, &workqueue_adr, 2);
+    libhexa_csum (buf, buf + HEXMINERA_TASK_SIZE + 5,
+                  buf + HEXMINERA_TASK_SIZE + 5);
+    if (info->wr_status != HEXA_STAT_IDLE)
+        return nr_len;
+    //if(info->start_up) cgsleep_ms(hexminera->device_id * HEXA_MAX_START_DELAY_MS);
+    ret = libhexa_sendHashData (hexminera, buf, nr_len);
+    if (ret != nr_len) {
+        libhexa_reset (hexminera);
+        mutex_lock (&info->lock);
+        info->usb_w_errors++;
+        mutex_unlock (&info->lock);
+        return -1;
+    }
+    if (info->reset_work) {
+        mutex_lock (&info->lock);
+        info->start_up  = false;
+        info->reset_work = false;
+        mutex_unlock (&info->lock);
+    }
+    return ret;
+}
+
+static inline void
+hexminera_create_task (bool reset_work, bool start_up, struct hexminera_task *ht, struct work *work)
+{
+    if (reset_work) {
+        //if(start_up) {
+        ht->status = HEXA_STAT_NEW_WORK_CLEAR_OLD;
+        //} else {
+        //  ht->status = HEXA_STAT_NEW_WORK_CLEAR_OLD;
+        //}
+    } else {
+        ht->status = HEXA_STAT_NEW_WORK;
+    }
+    memcpy (ht->midstate, work->midstate, 32);
+    memcpy (ht->merkle, work->data + 64, 12);
+    ht->id = (uint8_t) work->subid;
+    libhexa_calc_hexminer (work, ht);
+}
+
+static void *
+hexminera_send_tasks (void *userdata)
+{
+    struct cgpu_info *hexminera = (struct cgpu_info *) userdata;
+    struct hexminera_info *info = hexminera->device_data;
+    int64_t us_timeout;
+    char threadname[24];
+    snprintf (threadname, 24, "hexa_send/%d", hexminera->device_id);
+    RenameThread (threadname);
+    libhexa_reset (hexminera);
+    while(!libhexa_usb_dead(hexminera)) {
+        int start_count, end_count, ret;
+        cgtimer_t ts_start;
+        struct hexminera_task ht;
+        cgsleep_prepare_r (&ts_start);
+        us_timeout =
+            0x100000000ll / info->asic_count / info->frequency *
+            HEXMINERA_WORK_FACTOR;
+        mutex_lock (&info->lock);
+        start_count = info->read_pos;
+        end_count =
+            info->read_pos + MIN (info->cg_queue_cached_works,
+                                  HEXMINERA_ARRAY_MAX_POP);
+        while (info->read_pos < HEXMINERA_ARRAY_SIZE_REAL && info->hexworks[info->read_pos] != NULL &&
+               start_count < end_count && info->wr_status == HEXA_STAT_IDLE) {
+            hexminera_create_task (info->reset_work, info->start_up, &ht, info->hexworks[info->read_pos++]);
+            info->cg_queue_cached_works--;
+            mutex_unlock (&info->lock);
+            ret = hexminera_send_task (&ht, hexminera);
+            mutex_lock (&info->lock);
+            start_count++;
+        }
+        mutex_unlock (&info->lock);
+        libhexa_get_words (hexminera, HEXA_WORKANSWER_ADR + 4, 1);
+        cgsem_post(&info->qsem);
+        cgsleep_us_r (&ts_start, us_timeout);
+    }
+    pthread_exit (NULL);
+}
+
+static struct cgpu_info
+*hexminera_detect_one (libusb_device * dev, struct usb_find_devices *found)
+{
+    int miner_count, asic_count, frequency;
+    int this_option_offset = ++option_offset;
+    struct hexminera_info *info;
+    struct cgpu_info *hexminera;
+    bool configured;
+    int i = 0;
+    hexminera = usb_alloc_cgpu (&hexminera_drv, HEXA_MINER_THREADS);
+    if (!usb_init (hexminera, dev, found)) {
+        usb_uninit(hexminera);
+        return NULL;
+    }
+    hexminera->device_data = calloc (sizeof (struct hexminera_info), 1);
+    if (unlikely (!(hexminera->device_data))) {
+        hexminera->device_data = NULL;
+        usb_uninit(hexminera);
+        return NULL;
+    }
+    configured =
+        libhexa_get_options (this_option_offset, &asic_count, &frequency);
+    if (opt_hexminera_core_voltage < HEXA_MIN_COREMV
+        || opt_hexminera_core_voltage > HEXA_MAX_COREMV) {
+        applog
+        (LOG_ERR,
+         "Invalid hexminera-voltage %d must be %dmV - %dmV",
+         opt_hexminera_core_voltage, HEXA_MIN_COREMV, HEXA_MAX_COREMV);
+        free(hexminera->device_data);
+        hexminera->device_data = NULL;
+        usb_uninit(hexminera);
+        return NULL;
+    }
+    info = hexminera->device_data;
+    info->hexworks = calloc (sizeof (struct work *), HEXMINERA_ARRAY_SIZE);
+    if (unlikely (!(info->hexworks))) {
+        free(hexminera->device_data);
+        hexminera->device_data = NULL;
+        usb_uninit(hexminera);
+        return NULL;
+    }
+    while (i < HEXMINERA_ARRAY_SIZE) info->hexworks[i++] = NULL;
+    info->reset_work = true;
+    info->start_up = true;
+    info->read_pos = 0;
+    info->write_pos = 0;
+    info->cg_queue_cached_works = 0;
+    info->wr_status = HEXA_STAT_IDLE;
+    info->miner_count = HEXA_DEFAULT_MINER_NUM;
+    info->asic_count = HEXA_DEFAULT_ASIC_NUM;
+    info->frequency = HEXA_DEFAULT_FREQUENCY;
+    info->pic_voltage_readings = HEXA_DEFAULT_CORE_VOLTAGE;
+    info->core_voltage = opt_hexminera_core_voltage;
+    if (configured) {
+        info->asic_count = asic_count;
+        info->frequency = frequency;
+    }
+    if (!add_cgpu (hexminera)) {
+        free(info->hexworks);
+        free(hexminera->device_data);
+        hexminera->device_data = NULL;
+        hexminera = usb_free_cgpu (hexminera);
+        usb_uninit(hexminera);
+        return NULL;
+    }
+    libhexa_generatenrange_new ((unsigned char *) &info->nonces_range,
+                                info->asic_count);
+    return hexminera;
+}
+
+static void
+hexminera_detect (bool __maybe_unused hotplug)
+{
+    usb_detect (&hexminera_drv, hexminera_detect_one);
+}
+
+static void
+do_hexminera_close (struct thr_info *thr)
+{
+    struct cgpu_info *hexminera = thr->cgpu;
+    struct hexminera_info *info = hexminera->device_data;
+    int i = 0;
+    pthread_join (info->read_thr, NULL);
+    pthread_join (info->write_thr, NULL);
+    pthread_mutex_destroy (&info->lock);
+    cgsem_destroy(&info->qsem);
+    while (i < HEXMINERA_ARRAY_SIZE) {
+        if(info->hexworks[i] != NULL) free_work(info->hexworks[i]);
+        i++;
+    }
+    free (info->hexworks);
+    //usb_uninit(hexminera);
+    //Hotplug fucks up on full mem free :)
+    //free (hexminera->device_data);
+    //hexminera->device_data = NULL;
+    //thr->cgpu = usb_free_cgpu(hexminera);
+}
+
+static void
+hexminera_shutdown (struct thr_info *thr)
+{
+    struct cgpu_info *hexminera = thr->cgpu;
+    struct hexminera_info *info = hexminera->device_data;
+    if (!hexminera->shutdown) hexminera->shutdown = true;
+    cgsem_post(&info->qsem);
+    do_hexminera_close (thr);
+}
+
+static void *
+hexminera_get_results (void *userdata)
+{
+    struct cgpu_info *hexminera = (struct cgpu_info *) userdata;
+    struct hexminera_info *info = hexminera->device_data;
+    unsigned char readbuf[HEXA_HASH_BUF_SIZE];
+    struct worka_result *wr;
+    struct chip_resultsa *array_nonce_cache;
+    struct thr_info *thr = info->thr;
+    int i, lastchippos;
+    int usb_r_reset = 0;
+    int found;
+    uint32_t nonce;
+    char threadname[24];
+    int ret_r = 0, hash_read_pos = 0, hash_write_pos = 0, amount = 0;
+    wr = (struct worka_result *) malloc (sizeof (struct worka_result));
+    array_nonce_cache = calloc (16, sizeof (struct chip_resultsa));
+    int need_work_reset = 0;
+    bzero(array_nonce_cache, 16 * sizeof (struct chip_resultsa));
+    bzero(wr, sizeof (struct worka_result));
+    snprintf (threadname, 24, "hexa_recv/%d", hexminera->device_id);
+    RenameThread (threadname);
+    while(!libhexa_usb_dead(hexminera)) {
+        found = true;
+        cgtimer_t ts_start;
+        cgsleep_prepare_r (&ts_start);
+        /* Rotate */
+        ret_r = 0;
+        if ((hash_write_pos + HEXA_USB_R_SIZE + MAX_REPL_PACKET) >= HEXA_HASH_BUF_SIZE) {
+            hash_write_pos = hash_write_pos - hash_read_pos;
+            memcpy (readbuf, readbuf + hash_read_pos, hash_write_pos);
+            hash_read_pos = 0;
+        }
+        if (hash_write_pos - hash_read_pos >= HEXA_BASE_WORK_SIZE + 2) {
+again:
+            ret_r =
+                libhexa_eatHashData (wr, readbuf, &hash_read_pos,
+                                     &hash_write_pos);
+            if (ret_r == 1 && wr->status < HEXA_STAT_UNUSED) {
+                mutex_lock (&info->lock);
+                info->wr_status = wr->status;
+                mutex_unlock (&info->lock);
+            } else {
+                goto out;
+            }
+            if (wr->address != HEXA_WORKANSWER_ADR)
+                goto out;
+            if (wr->lastnonceid > HEXMINERA_ARRAY_SIZE_REAL ) {
+                wr->lastnonceid = 0;
+                need_work_reset++;
+            } else {
+                need_work_reset = 0;
+            }
+            found = 0;
+            nonce = htole32(wr->lastnonce);
+            i = 0;
+            while (i < info->asic_count) {
+                if (nonce < info->nonces_range[++i]) {
+                    lastchippos = --i;
+                    break;
+                }
+            }
+            if (i == info->asic_count)
+                lastchippos = info->asic_count - 1;
+            if (libhexa_cachenonce
+                (&array_nonce_cache[lastchippos], nonce) || need_work_reset < HEXA_USB_R_BAD_ID) {
+                uint8_t work_id = wr->lastnonceid;
+                found+=hexminera_predecode_nonce (hexminera, thr, nonce,
+                                                  work_id);
+                if (found>0) {
+                    mutex_lock (&info->lock);
+                    if(info->nonces == 0) libhexa_getvoltage (htole16 (wr->lastvoltage),
+                                &info->pic_voltage_readings);
+                    info->nonces+=found;
+                    info->matching_work[lastchippos]++;
+                    mutex_unlock (&info->lock);
+                } else {
+                    inc_hw_errors (thr);
+                }
+            } else {
+                mutex_lock (&info->lock);
+                info->dupe[lastchippos]++;
+                info->reset_work = true;
+                info->dev_reset_count++;
+                mutex_unlock (&info->lock);
+            }
+out:
+            if (ret_r == 2) {
+                mutex_lock (&info->lock);
+                info->usb_r_errors++;
+                mutex_unlock (&info->lock);
+            }
+        }
+        ret_r = libhexa_readHashData (hexminera, readbuf, &hash_write_pos, HEXMINERA_BULK_READ_TIMEOUT, true);
+        if (ret_r != LIBUSB_SUCCESS) {
+            usb_r_reset++;
+            if(usb_r_reset > HEXA_USB_RES_THRESH) {
+                libhexa_reset (hexminera);
+                usb_r_reset = 0;
+            }
+        } else {
+            usb_r_reset = 0;
+        }
+        //   if(libhexa_usb_dead(hexminera)) break;
+        cgsleep_us_r (&ts_start, HEXMINERA_READ_TIMEOUT);
+    }
+    free (wr);
+    free (array_nonce_cache);
+    pthread_exit (NULL);
+}
+
+static bool
+hexminera_prepare (struct thr_info *thr)
+{
+    struct cgpu_info *hexminera = thr->cgpu;
+    struct hexminera_info *info = hexminera->device_data;
+    info->thr = thr;
+    mutex_init (&info->lock);
+    cgsem_init(&info->qsem);
+    if (pthread_create
+        (&info->write_thr, NULL, hexminera_send_tasks, (void *) hexminera))
+        quit (1, "Failed to create hexminera write_thr");
+    if (pthread_create
+        (&info->read_thr, NULL, hexminera_get_results, (void *) hexminera))
+        quit (1, "Failed to create hexminera read_thr");
+    return true;
+}
+
+static int64_t
+hexminera_scanhash (struct thr_info *thr)
+{
+    struct cgpu_info *hexminera = thr->cgpu;
+    struct hexminera_info *info = hexminera->device_data;
+    struct work *work = NULL;
+    int64_t ms_timeout;
+    int64_t hash_count = 0;
+    /* 600 ms */
+    if(thr->work_restart) goto res;
+    ms_timeout = 600;
+    mutex_lock (&info->lock);
+    /* Rotate buffer */
+    if (info->read_pos >= HEXMINERA_ARRAY_SIZE_REAL
+        && info->write_pos >= HEXMINERA_ARRAY_SIZE_REAL ) {
+        info->write_pos = 0;
+        info->read_pos = 0;
+        info->cg_queue_cached_works = 0;
+    }
+    while(!(info->cg_queue_cached_works > HEXMINERA_PUSH_THRESH ||
+            info->write_pos >= HEXMINERA_ARRAY_SIZE_REAL)) {
+        mutex_unlock (&info->lock);
+        work = get_work(thr, thr->id);
+        mutex_lock (&info->lock);
+        if (work == NULL) break;
+        work->subid = info->write_pos;
+        if(info->hexworks[info->write_pos]!=NULL) free_work(info->hexworks[info->write_pos]);
+        info->hexworks[info->write_pos++] = work;
+        info->cg_queue_cached_works++;
+    }
+    hash_count = 0xffffffffull * (uint64_t) info->nonces;
+    info->nonces = 0;
+    mutex_unlock (&info->lock);
+    cgsem_mswait(&info->qsem, ms_timeout);
+res:
+    if (libhexa_usb_dead(hexminera)) {
+        if(!hexminera->shutdown) hexminera->shutdown = true;
+        return -1;
+    }
+    if(thr->work_restart) {
+        mutex_lock (&info->lock);
+        info->reset_work = true;
+        /* Eat Buffer */
+        info->read_pos = 0;
+        info->write_pos = 0;
+        //Shall we get work here? All other drivers quit because it becomes stale or?
+        info->cg_queue_cached_works = 0;
+        mutex_unlock (&info->lock);
+    }
+    return hash_count;
+}
+
+static void
+get_hexminera_statline_before (char *buf, size_t bufsiz,
+                               struct cgpu_info *hexminera)
+{
+    struct hexminera_info *info = hexminera->device_data;
+    tailsprintf (buf, bufsiz, "%3d %4d/%4dmV | ", info->frequency,
+                 info->core_voltage, info->pic_voltage_readings);
+}
+
+static struct api_data *
+hexminera_api_stats (struct cgpu_info *cgpu) {
+    struct api_data *root = NULL;
+    struct hexminera_info *info = cgpu->device_data;
+    uint64_t dh64, dr64;
+    double dev_runtime;
+    struct timeval now;
+    int i;
+    char displayed_hashes[16], displayed_rolling[16];
+    double hwp =
+        (cgpu->hw_errors +
+         cgpu->diff1) ? (double) (cgpu->hw_errors) / (double) (cgpu->hw_errors +
+                 cgpu->diff1) : 0;
+    if (cgpu->dev_start_tv.tv_sec == 0)
+        dev_runtime = total_secs;
+    else {
+        cgtime (&now);
+        dev_runtime = tdiff (&now, &(cgpu->dev_start_tv));
+    }
+    if (dev_runtime < 1.0)
+        dev_runtime = 1.0;
+    dh64 = (double) cgpu->total_mhashes / dev_runtime * 1000000ull;
+    dr64 = (double) cgpu->rolling * 1000000ull;
+    suffix_string (dh64, displayed_hashes, sizeof (displayed_hashes), 4);
+    suffix_string (dr64, displayed_rolling, sizeof (displayed_rolling), 4);
+    root = api_add_string (root, "MHS 5s", displayed_rolling, true);
+    root = api_add_string (root, "MHS av", displayed_hashes, true);
+    root = api_add_int (root, "Hardware Errors", &(cgpu->hw_errors), false);
+    root = api_add_percent (root, "Hardware Errors%", &hwp, true);
+    root = api_add_int (root, "USB Read Errors", &(info->usb_r_errors), false);
+    root = api_add_int (root, "USB Write Errors", &(info->usb_w_errors), false);
+    root = api_add_int (root, "Idled for 60 sec", &(info->idled), false);
+    root = api_add_int (root, "Reset Count", &(info->dev_reset_count), false);
+    root =
+        api_add_time (root, "Last Share Time", &(cgpu->last_share_pool_time),
+                      false);
+    root = api_add_int (root, "Chip Count", &(info->asic_count), false);
+    root = api_add_int (root, "Frequency", &(info->frequency), false);
+    root = api_add_int (root, "Core Voltage", &(info->core_voltage), false);
+    root =
+        api_add_int (root, "PIC Voltage Readings", &(info->pic_voltage_readings),
+                     false);
+    for (i = 0; i < info->asic_count; i++) {
+        char mcw[24];
+        sprintf (mcw, "Chip%d Nonces", i + 1);
+        root = api_add_int (root, mcw, &(info->matching_work[i]), false);
+        sprintf (mcw, "Chip%d Dupes", i + 1);
+        root = api_add_int (root, mcw, &(info->dupe[i]), false);
+    }
+    return root;
+}
+
+static bool hexminera_thread_init(struct thr_info *thr)
+{
+	struct cgpu_info *hexminera = thr->cgpu;
+	unsigned int wait;
+
+	/* Pause each new thread at least 100ms between initialising
+	 * so the devices aren't making calls all at the same time. */
+	wait = thr->id * HEXA_MAX_START_DELAY_MS;
+	//applog(LOG_DEBUG, "%s%d: Delaying start by %dms",
+			//hexminera->drv->name, hexminera->device_id, wait / 1000);
+	cgsleep_ms(wait);
+
+	return true;
+}
+
+struct device_drv hexminera_drv = {
+    .drv_id = DRIVER_hexminera,
+    .dname = "hexminera",
+    .name = "HEXa",
+    .drv_detect = hexminera_detect,
+    .thread_prepare = hexminera_prepare,
+    //.thread_init = hexminera_thread_init,
+    .hash_work = hash_queued_work,
+    .scanwork = hexminera_scanhash,
+    .flush_work = hexminera_flush_work,
+    .get_api_stats = hexminera_api_stats,
+    .get_statline_before = get_hexminera_statline_before,
+    .thread_shutdown = hexminera_shutdown,
+};
--- cg_o/driver-hexminera.h	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/driver-hexminera.h	2013-11-26 09:34:57.148117824 +0200
@@ -0,0 +1,154 @@
+/*$T indentinput.h GC 1.140 10/16/13 10:20:01 */
+
+/*
+ * Copyright 2013 Avalon project Copyright 2013 Con Kolivas <kernel@kolivas.org>
+ * 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. Thank you guy
+ */
+#ifndef HEXA_H
+#define HEXA_H
+
+#ifdef USE_HEXMINERA
+#include "util.h"
+
+/* hexminera_task/work_reply status Definitions: */
+#define HEXA_STAT_IDLE					0       /* Idle or data already Sent to the buffer */
+#define HEXA_STAT_NEW_WORK				1       /* Request for write in the buffer */
+#define HEXA_STAT_WAITING				2       /* Wait For Buffer Empty Position */
+#define HEXA_STAT_CLR_BUFF				3       /* Force Buffer Empty */
+#define HEXA_STAT_STOP_REQ				4       /* Stop Request */
+#define HEXA_STAT_NEW_WORK_CLEAR_OLD		5       /* Clear Buffers and after that fill the first buffer */
+#define HEXA_STAT_UNUSED					6
+
+#define HEXA_USB_RES_THRESH				7000 //about 1 sec 
+#define HEXA_DEFAULT_XCLKIN_CLOCK		32      /* In MHz */
+#define HEXA_CLOCK_LOW_CFG				0x00030017
+#define HEXA_CLOCK_HIGH_CFG				(0x0000002e << 3)       /* = 0x00000170 */
+#define HEXMINERA_ARRAY_PIC_SIZE		64
+#define HEXMINERA_ARRAY_SIZE			HEXMINERA_ARRAY_PIC_SIZE * 4
+#define HEXMINERA_ARRAY_SIZE_REAL	HEXMINERA_ARRAY_SIZE - 2
+#define HEXA_NONCE_CASH_SIZE				2
+#define HEXMINERA_WORK_FACTOR		0.90    /* We need to be aggressive and fill PIC faster than time taken for a job
+* to finish. After pic is full we are going to keep that way and leave no
+* room for potential usb issues timeout:) */
+#define HEXMINERA_PUSH_THRESH		4       /* At least 3 queued works available to be written to PIC */
+#define HEXMINERA_ARRAY_MAX_POP		1
+#define HEXA_USB_R_SIZE					1
+#define MAX_REPL_PACKET					0x0f
+#define HEXA_USB_R_BAD_ID					10
+#define HEXA_USB_WR_SIZE					62
+#define HEXA_HASH_BUF_SIZE				2048
+#define HEXA_USB_WR_TIME_OUT				0
+#define HEXMINERA_READ_TIMEOUT		140
+#define HEXMINERA_BULK_READ_TIMEOUT		0
+#define HEXA_MAX_START_DELAY_MS			1000
+#define HEXA_MINER_THREADS			1
+#define HEXA_DEFAULT_MINER_NUM		0x01
+#define HEXA_DEFAULT_ASIC_NUM		0x10
+#define HEXA_MIN_FREQUENCY			100
+#define HEXA_MAX_FREQUENCY			11650
+#define HEXA_DEFAULT_FREQUENCY		282
+#define HEXA_DEFAULT_CORE_VOLTAGE	1200    /* in millivolts */
+#define HEXA_MIN_COREMV				1000    /* in millivolts */
+
+/* Do not touch it!!! 1.6V is above the chip specs already */
+#define HEXA_MAX_COREMV	1630    /* in millivolts */
+
+struct chip_resultsa {
+    uint8_t nonce_cache_write_pos;
+    uint32_t nonces[HEXA_NONCE_CASH_SIZE];
+    };
+
+struct worka_result {
+    uint8_t startbyte;
+    uint8_t datalength;
+    uint8_t command;
+    uint16_t address;
+    uint32_t lastnonce;
+    uint8_t lastnonceid;
+    uint8_t status;
+    uint16_t lastvoltage;
+    uint16_t lasttemperature;
+    uint16_t lastfanrpm;
+    uint32_t serial;
+    uint16_t openloadduty;
+    uint16_t workingduty;
+    uint16_t lastworkingduty;
+    uint16_t clockforce;          /* Times Avalons Crashed */
+    uint8_t pad[3];
+} __attribute__ ((packed, aligned (4)));
+
+struct hexminera_info {
+    int miner_count;
+    int asic_count;
+    int core_voltage;
+    int frequency;
+    int idled;
+    int nonces;
+    int read_pos;
+    int write_pos;
+    int usb_r_errors;
+    int usb_w_errors;
+    int dev_reset_count;
+    int pic_voltage_readings;
+    int64_t usb_timing;
+    int cg_queue_cached_works;
+    int dupe[HEXA_DEFAULT_ASIC_NUM];
+    int matching_work[HEXA_DEFAULT_ASIC_NUM];
+    bool reset_work;
+    bool start_up;
+    uint8_t wr_status;
+    uint8_t wr_lastnonceid;
+    uint32_t nonces_range[HEXA_DEFAULT_ASIC_NUM];
+    pthread_t read_thr;
+    pthread_t write_thr;
+    pthread_mutex_t lock;
+    cgsem_t qsem;
+    struct thr_info *thr;
+    struct work **hexworks;
+};
+
+
+/*
+ -----------------------------------------------------------------------------------------------------------------------
+    2 + 3 + 1 + 1 + 1 + 1 + 1 + 8 + 1 + 1 + 1 + 2 = 23(uint32_t)=46(uint16_t)=
+ -----------------------------------------------------------------------------------------------------------------------
+ */
+struct hexminera_task {
+    uint32_t clockcfg[2];
+    uint32_t merkle[3];
+    uint32_t a1;
+    uint32_t a0;
+    uint32_t e2;
+    uint32_t e1;
+    uint32_t e0;
+    uint8_t midstate[32];
+    uint32_t a2;
+    uint32_t startnonce;
+    uint8_t id;
+    uint8_t status;
+    uint16_t hashclock;
+    uint16_t chipcount;
+    uint16_t refvoltage;
+    uint16_t reftemperature;
+    uint16_t reffanrpm;
+} __attribute__ ((packed, aligned (4)));
+
+#define HEXA_WORKANSWER_ADR	0x3000
+#define HEXA_WORKQUEUE_ADR	0x4000
+#define HEXA_PTCON_ADR		0x0C00
+#define HEXA_START_STOP_ADR	0x646E
+#define HEXMINERA_TASK_SIZE	(sizeof(struct hexminera_task))
+#define HEXA_MAX_WORK_SIZE		(sizeof(struct worka_result) - 3)
+#define HEXA_BASE_WORK_SIZE		6       /* Min uint8_t startbyte + uint8_t datalength + uint8_t command + uint16_t
+* address;
+* + uint8_t csum */
+
+extern int opt_hexminera_core_voltage;
+extern char *libhexa_set_config_voltage (char *arg);
+extern struct hexminera_info **hexminera_info;
+#endif /* USE_HEXMINERA */
+#endif /* HEXA_H */
--- cg_o/libhexa.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/libhexa.c	2013-11-26 09:34:57.148117824 +0200
@@ -0,0 +1,423 @@
+/*$T indentinput.c GC 1.140 10/16/13 10:20:34 */
+#define rotate(x, y)	((x << y) | (x >> (sizeof(x) * 8 - y)))
+#define rotr(x, y)		((x >> y) | (x << (sizeof(x) * 8 - y)))
+#define R(a, b, c, d, e, f, g, h, w, k) \
+		h = h + \
+		(rotate(e, 26) ^ rotate(e, 21) ^ rotate(e, 7)) + \
+		(g ^ (e & (f ^ g))) + \
+		k + \
+		w; \
+	d = d + h; \
+	h = h + (rotate(a, 30) ^ rotate(a, 19) ^ rotate(a, 10)) + ((a & b) | (c & (a | b)))
+const uint32_t SHA256_K[3] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf };
+
+static bool
+libhexa_cachenonce (struct chip_resultsa *nonce_cache, uint32_t nonce)
+{
+    int i = 0;
+    while (i < HEXA_NONCE_CASH_SIZE && nonce_cache->nonces[i] != nonce)
+        i++;
+    if (i < HEXA_NONCE_CASH_SIZE)
+        return false;
+    //Rotate
+    if (nonce_cache->nonce_cache_write_pos == HEXA_NONCE_CASH_SIZE)
+        nonce_cache->nonce_cache_write_pos = 0;
+    nonce_cache->nonces[nonce_cache->nonce_cache_write_pos++] = nonce;
+    return true;
+}
+
+static void
+libhexa_generatenrange_new (unsigned char *buf, int asic_num)
+{
+    uint32_t nonceAdd;
+    int noncePos;
+    int64_t nonceCalc = 0x100000000ll;
+    nonceCalc /= asic_num;
+    nonceAdd = (uint32_t) nonceCalc;
+    uint32_t chip_noce;
+    for (noncePos = 0; noncePos < asic_num; noncePos++) {
+        /*
+         * chip_noce = htole32(noncePos * nonceAdd);
+         */
+        chip_noce = noncePos * nonceAdd;
+        memcpy (buf + noncePos * 4, &chip_noce, 4);
+    }
+}
+
+char *
+libhexa_set_config_voltage (char *arg)
+{
+    int val1, ret;
+    ret = sscanf (arg, "%d", &val1);
+    if (ret < 1)
+        return "No values passed to hexminera-voltage";
+    if (val1 < HEXA_MIN_COREMV || val1 > HEXA_MAX_COREMV)
+        return "Invalid value passed to hexminera-voltage";
+    opt_hexminera_core_voltage = val1;
+    return NULL;
+}
+/*
+    Thanks to BkkCoins & devileraser!
+ */
+
+static void
+libhexa_calc_hexminer (struct work *work, struct hexminera_task *ht)
+{
+    uint32_t a0a1a2e0e1e2[6];
+    uint32_t A, B, C, D, E, F, G, H, T;
+    uint32_t state[8];
+    uint32_t data[3];
+    memcpy (&state, work->midstate, 32);
+    memcpy (&data, work->data + 64, 12);
+#if defined(__BIG_ENDIAN__) || defined(MIPSEB)
+    int i;
+    for (i = 0; i < 8; i++)
+        state[i] = htole32 (state[i]);
+    for (i = 0; i < 3; i++)
+        data[i] = htole32 (data[i]);
+#endif
+    A = state[0];
+    B = state[1];
+    C = state[2];
+    D = state[3];
+    E = state[4];
+    F = state[5];
+    G = state[6];
+    H = state[7];
+    R (A, B, C, D, E, F, G, H, data[0], SHA256_K[0]);
+    a0a1a2e0e1e2[0] = htole32 (H);
+    a0a1a2e0e1e2[3] = htole32 (D);
+    R (H, A, B, C, D, E, F, G, data[1], SHA256_K[1]);
+    a0a1a2e0e1e2[1] = htole32 (G);
+    a0a1a2e0e1e2[4] = htole32 (C);
+    R (G, H, A, B, C, D, E, F, data[2], SHA256_K[2]);
+    a0a1a2e0e1e2[2] = htole32 (F);
+    a0a1a2e0e1e2[5] = htole32 (B);
+    memcpy (&ht->a0, &a0a1a2e0e1e2[0], 4);
+    memcpy (&ht->a1, &a0a1a2e0e1e2[1], 4);
+    memcpy (&ht->a2, &a0a1a2e0e1e2[2], 4);
+    memcpy (&ht->e0, &a0a1a2e0e1e2[3], 4);
+    memcpy (&ht->e1, &a0a1a2e0e1e2[4], 4);
+    memcpy (&ht->e2, &a0a1a2e0e1e2[5], 4);
+}
+/*
+    From Hexminer core developer Thanks!
+ */
+
+static void
+libhexa_generateclk (uint16_t HashClock, uint16_t XCLKIN, uint32_t * res)
+{
+    uint32_t configL = 0;
+    uint32_t configH = 0;
+    int RValue = XCLKIN;
+    int NValue = (HashClock * 2 * RValue / XCLKIN);
+    configL =
+        ((uint32_t) RValue << 29) | ((uint32_t) NValue << 18) | HEXA_CLOCK_LOW_CFG;
+    configH = ((uint32_t) RValue >> 3) | HEXA_CLOCK_HIGH_CFG;
+    res[0] = htole32 (configL);
+    res[1] = htole32 (configH);
+}
+
+static void
+libhexa_csum (unsigned char *startptr, unsigned char *endptr,
+              unsigned char *resptr)
+{
+	
+    unsigned char *b = startptr;
+    uint8_t sum = 0;
+    while (b < endptr)
+        sum += *b++;
+    memcpy (resptr, &sum, 1);
+}
+
+static bool
+libhexa_get_options (int this_option_offset, int *asic_count, int *frequency)
+{
+    char buf[BUFSIZ + 1];
+    char *ptr, *comma, *colon, *colon2, *colon3, *colon4;
+    bool timeout_default;
+    size_t max;
+    int i, tmp;
+    if (opt_hexminera_options == NULL)
+        buf[0] = '\0';
+    else {
+        ptr = opt_hexminera_options;
+        for (i = 0; i < this_option_offset; i++) {
+            comma = strchr (ptr, ',');
+            if (comma == NULL)
+                break;
+            ptr = comma + 1;
+        }
+        comma = strchr (ptr, ',');
+        if (comma == NULL)
+            max = strlen (ptr);
+        else
+            max = comma - ptr;
+        if (max > BUFSIZ)
+            max = BUFSIZ;
+        strncpy (buf, ptr, max);
+        buf[max] = '\0';
+    }
+    if (!(*buf))
+        return false;
+    colon = strchr (buf, ':');
+    if (colon)
+        *(colon++) = '\0';
+    tmp = atoi (buf);
+    if (tmp > 0 && tmp <= HEXA_DEFAULT_ASIC_NUM)
+        *asic_count = tmp;
+    else {
+        quit (1,
+              "Invalid hexminera-options for " "asic_count (%s) must be 1 ~ %d",
+              buf, HEXA_DEFAULT_ASIC_NUM);
+    }
+    if (colon && *colon) {
+        tmp = atoi (colon);
+        if (tmp < HEXA_MIN_FREQUENCY || tmp > HEXA_MAX_FREQUENCY) {
+            quit
+            (1,
+             "Invalid hexminera-options for frequency (%s) must be %d <= frequency <= %d",
+             colon, HEXA_MIN_FREQUENCY, HEXA_MAX_FREQUENCY);
+        }
+        *frequency = tmp;
+    }
+    return true;
+}
+
+static bool libhexa_usb_dead
+(struct cgpu_info *hexminera)
+{
+    struct cg_usb_device *usbdev;
+    usbdev = hexminera->usbdev;
+    return (usbdev == NULL
+            || usbdev->handle == NULL
+            || hexminera->shutdown
+            || hexminera->usbinfo.nodev || hexminera->deven != DEV_ENABLED);
+}
+
+static int
+libhexa_sendHashData (struct cgpu_info *hexminera, unsigned char *sendbuf,
+                      size_t buf_len)
+{
+    struct hexminera_info *info = hexminera->device_data;
+    struct cg_usb_device *usbdev;
+    int wrote = 0, written = 0;
+    int err = LIBUSB_SUCCESS;
+    int pstate;
+    usb_lock_w (hexminera, pstate);
+    usbdev = hexminera->usbdev;
+    if(libhexa_usb_dead(hexminera))
+        goto out;
+    while (written < buf_len && err == LIBUSB_SUCCESS) {
+        err = libusb_bulk_transfer
+              (usbdev->handle,
+               0x02,
+               sendbuf + written,
+               MIN (HEXA_USB_WR_SIZE, buf_len - written), &wrote, HEXA_USB_WR_TIME_OUT);
+        if(err == LIBUSB_SUCCESS) written += wrote;
+    }
+out:
+    usb_unlock_w (hexminera, pstate);
+    return written;
+}
+
+static void
+libhexa_reset (struct cgpu_info *hexminera)
+{
+    struct hexminera_info *info = hexminera->device_data;
+    struct cg_usb_device *usbdev;
+    int err = LIBUSB_SUCCESS;
+    int pstate;
+    usb_lock_w (hexminera, pstate);
+    usbdev = hexminera->usbdev;
+    if(libhexa_usb_dead(hexminera))
+        goto out;
+    err = libusb_reset_device (usbdev->handle);
+out:
+    usb_unlock_w (hexminera, pstate);
+}
+
+static int libhexa_readHashData
+(struct cgpu_info *hexminera,
+ unsigned char *hash, int *hash_write_pos, int timeout, bool read_once)
+{
+    struct hexminera_info *info = hexminera->device_data;
+    struct cg_usb_device *usbdev;
+    int read = 0, total = 0;
+    int err = LIBUSB_SUCCESS;
+    int pstate;
+    //hack HEX16A only
+    if(info->start_up) return err;
+    usb_lock_r (hexminera, pstate);
+    usbdev = hexminera->usbdev;
+    if(libhexa_usb_dead(hexminera))
+        goto out;
+    while (*hash_write_pos + HEXA_USB_R_SIZE < HEXA_HASH_BUF_SIZE
+           && err == LIBUSB_SUCCESS) {
+        err =
+            libusb_bulk_transfer (usbdev->handle, 0x82, hash + *hash_write_pos,
+                                  HEXA_USB_R_SIZE, &read, timeout);
+        if(err == LIBUSB_SUCCESS) {
+            *hash_write_pos += read;
+            total += read;
+        }
+        if (read_once)
+            break;
+    }
+out:
+    usb_unlock_r (hexminera, pstate);
+    if (err == LIBUSB_ERROR_NO_DEVICE || err == LIBUSB_ERROR_NOT_FOUND) {
+        hexminera->shutdown = true;
+        cgsem_post(&info->qsem);
+    }
+    return err;
+}
+
+static int
+hexminera_predecode_nonce (struct cgpu_info *hexminera, struct thr_info *thr,
+                           uint32_t nonce, uint8_t work_id)
+{
+    struct hexminera_info *info = hexminera->device_data;
+    int res = 0;
+    mutex_lock (&info->lock);
+    if (info->hexworks[work_id] == NULL) goto out;
+    if (test_nonce (info->hexworks[work_id], nonce)) {
+        submit_tested_work (thr, info->hexworks[work_id]);
+        res = 1;
+    }
+out:
+    mutex_unlock (&info->lock);
+    return res;
+}
+/*
+    From Hexminer core developer Thanks!
+ */
+
+static void
+libhexa_getvoltage (uint16_t wr_bukvoltage, int *info_pic_voltage_readings)
+{
+    float voltagehuman;
+    voltagehuman =
+        (float) ((float) wr_bukvoltage * (float) 1000 * (float) 3.3 /
+                 ((1 << 12) - 1));
+    *info_pic_voltage_readings = (int) voltagehuman;
+}
+/*
+    From Hexminer core developer Thanks!
+ */
+
+static void
+libhexa_setvoltage (int info_voltage, uint16_t * refvoltage)
+{
+    uint16_t voltageadc;
+    voltageadc =
+        (uint16_t) ((float) info_voltage / (float) 1000 / (float) 3.3 *
+                    ((1 << 12) - 1));
+    *refvoltage = htole16 (voltageadc);
+}
+
+static int
+libhexa_eatHashData (struct worka_result *wr, unsigned char *hash,
+                     int *hash_read_pos, int *hash_write_pos)
+{
+    uint8_t psum;
+    int wrpos;
+    unsigned char *csum_pos;
+    bool ok;
+eat:
+    while (*hash_read_pos < *hash_write_pos && hash[*hash_read_pos] != 0x53) {
+        *hash_read_pos += 1;
+    }
+    if (*hash_write_pos - *hash_read_pos < HEXA_BASE_WORK_SIZE)
+        goto done;
+    memcpy ((char *) &wr->startbyte, &hash[*hash_read_pos],
+            HEXA_BASE_WORK_SIZE - 1);
+    wr->address = htole16 (wr->address);
+    /* Address is outside be strict to avoid mem corruption - not fancy but it works*/
+    ok = (wr->command == 0x52) &&
+         (
+             (wr->address == HEXA_WORKANSWER_ADR && wr->datalength == 0x06)
+             || (wr->address == HEXA_WORKANSWER_ADR && wr->datalength == 0x0C)
+             || (wr->address == HEXA_WORKANSWER_ADR+4 && wr->datalength == 1)
+         );
+    if(!ok) {
+        *hash_read_pos += 1;
+        goto eat;
+    }
+    if (*hash_write_pos - *hash_read_pos <
+        HEXA_BASE_WORK_SIZE + wr->datalength * 2)
+        goto done;
+    csum_pos =
+        hash + *hash_read_pos + HEXA_BASE_WORK_SIZE + wr->datalength * 2 - 1;
+    //Crap?
+    if(csum_pos - hash < HEXA_HASH_BUF_SIZE) {
+        //That was writing somewhere and corrupting memory because of faulty usb reads....
+        libhexa_csum (hash + *hash_read_pos, csum_pos, &psum);
+        if (psum != *csum_pos) {
+            *hash_read_pos += 1;
+            return 2;
+        }
+    } else {
+        *hash_read_pos += 1;
+        return 2;
+    }
+    wrpos = (wr->address - HEXA_WORKANSWER_ADR) + HEXA_BASE_WORK_SIZE - 1;
+    memcpy
+    ((char *) &wr->startbyte + wrpos,
+     &hash[*hash_read_pos + HEXA_BASE_WORK_SIZE - 1],
+     MIN (wr->datalength * 2, HEXA_MAX_WORK_SIZE - HEXA_BASE_WORK_SIZE - 1));
+    *hash_read_pos += HEXA_BASE_WORK_SIZE + wr->datalength * 2;
+    return 1;
+done:
+    return 0;
+}
+
+static void
+BitUpdateInRAMAndSend (struct cgpu_info *hexminera, uint16_t address,
+                       uint16_t bitPos, bool value)
+{
+    unsigned char buf[10];
+    uint16_t wr_adr = htole16 (address);
+    buf[0] = 0x53;
+    buf[1] = 0x01;
+    buf[2] = 0x42;
+    memcpy (buf + 3, &wr_adr, 2);
+    if (value == true) {
+        buf[6] = 0x80;
+    } else {
+        buf[6] = 0x00;
+    }
+    buf[5] = bitPos;
+    libhexa_csum (buf, buf + 7, buf + 7);
+    libhexa_sendHashData (hexminera, buf, 8);
+}
+
+static void
+libhexa_get_words (struct cgpu_info *hexminera, uint16_t address, uint8_t words)
+{
+    unsigned char status[10];
+    uint16_t wr_adr = htole16 (address);
+    status[0] = 0x53;
+    status[1] = 0x01;
+    status[2] = 0x52;
+    memcpy (status + 3, &wr_adr, 2);
+    status[5] = words;
+    status[6] = 0x00;
+    libhexa_csum (status, status + 7, status + 7);
+    libhexa_sendHashData (hexminera, status, 8);
+}
+
+static void
+libhexa_set_word (struct cgpu_info *hexminera, uint16_t address, uint16_t word)
+{
+    unsigned char status[10];
+    uint16_t wr_adr = htole16 (address);
+    uint16_t ledata = htole16 (word);
+    status[0] = 0x53;
+    status[1] = 0x01;
+    status[2] = 0x57;
+    memcpy (status + 3, &wr_adr, 2);
+    memcpy (status + 5, &ledata, 2);
+    libhexa_csum (status, status + 7, status + 7);
+    libhexa_sendHashData (hexminera, status, 8);
+}
--- cg_o/hubpower.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/hubpower.c	2013-11-26 09:34:57.148117824 +0200
@@ -0,0 +1,280 @@
+/* hubpower -- control the power settings for a USB hub
+ *
+ * To build: gcc -o hubpower hubpower.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+//#include <strings.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <asm/byteorder.h>
+#include <linux/usbdevice_fs.h>
+#include <linux/usb/ch9.h>
+
+#define USB_HUB_TIMEOUT     5000    /* milliseconds */
+#define USB_PORT_FEAT_POWER 8
+
+#define USB_DT_HUB      (USB_TYPE_CLASS | 0x09)
+#define USB_DT_HUB_SIZE     7
+
+struct usb_hub_descriptor {
+    __u8  bDescLength;
+    __u8  bDescriptorType;
+    __u8  bNbrPorts;
+    __le16 wHubCharacteristics;
+    __u8  bPwrOn2PwrGood;
+    __u8  bHubContrCurrent;
+} __attribute__ ((packed));
+
+struct usb_port_status {
+    __le16 wPortStatus;
+    __le16 wPortChange;
+} __attribute__ ((packed));
+
+#define USB_PORT_STAT_CONNECTION    0x0001
+#define USB_PORT_STAT_ENABLE        0x0002
+#define USB_PORT_STAT_SUSPEND       0x0004
+#define USB_PORT_STAT_OVERCURRENT   0x0008
+#define USB_PORT_STAT_RESET     0x0010
+#define USB_PORT_STAT_L1        0x0020
+/* bits 6 to 7 are reserved */
+#define USB_PORT_STAT_POWER     0x0100
+#define USB_PORT_STAT_LOW_SPEED     0x0200
+#define USB_PORT_STAT_HIGH_SPEED        0x0400
+#define USB_PORT_STAT_TEST              0x0800
+#define USB_PORT_STAT_INDICATOR         0x1000
+#define USB_PORT_STAT_POWER_3       0x0200  /* USB 3.0 */
+
+
+int fd;     /* Hub device file */
+int usb_level;
+
+
+void usage(void)
+{
+    fprintf(stderr, "Usage:"
+        "\thubpower busnum:devnum power {portnum (on|off)} ...\n"
+        "\thubpower busnum:devnum status\n"
+        "\thubpower busnum:devnum bind\n"
+        );
+    exit(1);
+}
+
+void port_status(int portnum)
+{
+    struct usbdevfs_ctrltransfer ctrl;
+    struct usb_port_status pstat;
+    int rc;
+
+    ctrl.bRequestType = USB_DIR_IN | USB_TYPE_CLASS |
+            USB_RECIP_OTHER;
+    ctrl.bRequest = USB_REQ_GET_STATUS;
+    ctrl.wValue = 0;
+    ctrl.wIndex = portnum;
+    ctrl.wLength = sizeof(pstat);
+    ctrl.timeout = USB_HUB_TIMEOUT;
+    ctrl.data = &pstat;
+    rc = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+    if (rc == -1) {
+        fprintf(stderr, "Error in ioctl "
+            "(get port %d status): %s\n",
+            portnum, strerror(errno));
+        return;
+    }
+
+    printf("Port %2d status: %04x ", portnum, pstat.wPortStatus);
+
+    if (usb_level <= 2) {
+        if (pstat.wPortStatus & USB_PORT_STAT_INDICATOR)
+            printf(" Indicator");
+        if (pstat.wPortStatus & USB_PORT_STAT_TEST)
+            printf(" Test-Mode");
+        if (pstat.wPortStatus & USB_PORT_STAT_HIGH_SPEED)
+            printf(" High-Speed");
+        if (pstat.wPortStatus & USB_PORT_STAT_LOW_SPEED)
+            printf(" Low-Speed");
+        if (pstat.wPortStatus & USB_PORT_STAT_POWER)
+            printf(" Power-On");
+        else
+            printf(" Power-Off");
+    } else if (usb_level == 3) {
+        if (pstat.wPortStatus & USB_PORT_STAT_POWER_3)
+            printf(" Power-On");
+        else
+            printf(" Power-Off");
+    }
+
+    if (pstat.wPortStatus & USB_PORT_STAT_RESET)
+        printf(" Resetting");
+    if (pstat.wPortStatus & USB_PORT_STAT_OVERCURRENT)
+        printf(" Overcurrent");
+    if (pstat.wPortStatus & USB_PORT_STAT_SUSPEND)
+        printf(" Suspended");
+    if (pstat.wPortStatus & USB_PORT_STAT_ENABLE)
+        printf(" Enabled");
+    if (pstat.wPortStatus & USB_PORT_STAT_CONNECTION)
+        printf(" Connected");
+
+    printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+    int busnum, devnum, numports;
+    enum {DO_POWER, DO_STATUS, DO_BIND} action;
+    char fname1[40], fname2[40];
+    int rc;
+    int portnum;
+    struct usb_device_descriptor dev_descr;
+    struct usb_hub_descriptor hub_descr;
+    struct usbdevfs_ctrltransfer ctrl;
+    struct usbdevfs_ioctl usb_ioctl;
+    int bus_endian;
+
+    if (argc < 3)
+        usage();
+    if (sscanf(argv[1], "%d:%d", &busnum, &devnum) != 2 ||
+            busnum <= 0 || busnum > 255 ||
+            devnum <= 0 || devnum > 255)
+        usage();
+
+    if (strcmp(argv[2], "power") == 0) {
+        action = DO_POWER;
+        if ((argc - 3) % 2 != 0)
+            usage();
+    } else if (strcmp(argv[2], "status") == 0) {
+        action = DO_STATUS;
+        if (argc != 3)
+            usage();
+    } else if (strcmp(argv[2], "bind") == 0) {
+        action = DO_BIND;
+        if (argc != 3)
+            usage();
+    } else {
+        usage();
+    }
+
+    sprintf(fname1, "/dev/bus/usb/%03d/%03d", busnum, devnum);
+    sprintf(fname2, "/proc/bus/usb/%03d/%03d", busnum, devnum);
+
+    bus_endian = 1;
+    fd = open(fname1, O_RDWR);
+    if (fd < 0) {
+        int err1 = errno;
+
+        bus_endian = 0;
+        fd = open(fname2, O_RDWR);
+        if (fd < 0) {
+            fprintf(stderr, "Unable to open device file %s: %s\n",
+                    fname1, strerror(err1));
+            fprintf(stderr, "Unable to open device file %s: %s\n",
+                    fname2, strerror(errno));
+            return 1;
+        }
+    }
+
+    rc = read(fd, &dev_descr, USB_DT_DEVICE_SIZE);
+    if (rc != USB_DT_DEVICE_SIZE) {
+        perror("Error reading device descriptor");
+        return 1;
+    }
+    if (dev_descr.bDeviceClass != USB_CLASS_HUB) {
+        fprintf(stderr, "Device %d:%d is not a hub\n",
+                busnum, devnum);
+        return 1;
+    }
+    if (bus_endian) {
+        dev_descr.bcdUSB = __le16_to_cpu(dev_descr.bcdUSB);
+    }
+    usb_level = dev_descr.bcdUSB >> 8;
+
+    ctrl.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE;
+    ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+    ctrl.wValue = USB_DT_HUB << 8;
+    ctrl.wIndex = 0;
+    ctrl.wLength = USB_DT_HUB_SIZE;
+    ctrl.timeout = USB_HUB_TIMEOUT;
+    ctrl.data = &hub_descr;
+    rc = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+    if (rc == -1) {
+        perror("Error in ioctl (read hub descriptor)");
+        return 1;
+    }
+    numports = hub_descr.bNbrPorts;
+
+    if (action == DO_STATUS) {
+        for (portnum = 1; portnum <= numports; ++portnum)
+            port_status(portnum);
+        return 0;
+    }
+
+    if (action == DO_BIND) {
+        usb_ioctl.ifno = 0;
+        usb_ioctl.ioctl_code = USBDEVFS_CONNECT;
+        usb_ioctl.data = NULL;
+        rc = ioctl(fd, USBDEVFS_IOCTL, &usb_ioctl);
+        if (rc == -1) {
+            perror("Error in ioctl (USBDEVFS_CONNECT)");
+            return 1;
+        }
+        printf("Bind-driver request sent to the kernel\n");
+        return 0;
+    }
+
+    if (action == DO_POWER) {
+        int i;
+
+        usb_ioctl.ifno = 0;
+        usb_ioctl.ioctl_code = USBDEVFS_DISCONNECT;
+        usb_ioctl.data = NULL;
+        rc = ioctl(fd, USBDEVFS_IOCTL, &usb_ioctl);
+        if (rc == -1 && errno != ENODATA) {
+            perror("Error in ioctl (USBDEVFS_DISCONNECT)");
+            return 1;
+        }
+
+        for (i = 3; i < argc; i += 2) {
+            portnum = atoi(argv[i]);
+            if (portnum < 1 || portnum > numports) {
+                fprintf(stderr, "Invalid port number: %d\n",
+                        portnum);
+                continue;
+            }
+
+            if (strcmp(argv[i+1], "on") == 0)
+                ctrl.bRequest = USB_REQ_SET_FEATURE;
+            else if (strcmp(argv[i+1], "off") == 0)
+                ctrl.bRequest = USB_REQ_CLEAR_FEATURE;
+            else {
+                fprintf(stderr, "Invalid port power level: %s\n)",
+                        argv[i+1]);
+                continue;
+            }
+
+            ctrl.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS |
+                    USB_RECIP_OTHER;
+            ctrl.wValue = USB_PORT_FEAT_POWER;
+            ctrl.wIndex = portnum;
+            ctrl.wLength = 0;
+            ctrl.timeout = USB_HUB_TIMEOUT;
+            ctrl.data = NULL;
+            rc = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+            if (rc == -1) {
+                fprintf(stderr, "Error in ioctl "
+                    "(set/clear port %d feature): %s\n",
+                    portnum, strerror(errno));
+                continue;
+            }
+
+            port_status(portnum);
+        }
+    }
+    return 0;
+}
+
+
--- cg_o/driver-hexminerc.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/driver-hexminerc.c	2013-11-26 09:34:57.148117824 +0200
@@ -0,0 +1,530 @@
+/*$T indentinput.c GC 1.140 10/16/13 10:19:47 */
+/*
+ * Copyright 2013 Con Kolivas <kernel@kolivas.org> Copyright 2012-2013 Xiangfu
+ * <xiangfu@openmobilefree.com> Copyright 2012 Luke Dashjr Copyright 2012 Andrew
+ * Smith 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. Thank you guys!
+ */
+#include "config.h"
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <unistd.h>
+#ifndef WIN32
+#include <sys/select.h>
+#include <termios.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifndef O_CLOEXEC
+#define O_CLOEXEC	0
+#endif
+#else
+#include "compat.h"
+#include <windows.h>
+#include <io.h>
+#endif
+#include "elist.h"
+#include "miner.h"
+#include "usbutils.h"
+#include "driver-hexminerc.h"
+#include "util.h"
+
+static int option_offset = -1;
+struct device_drv hexminerc_drv;
+int opt_hexminerc_core_voltage = HEXC_DEFAULT_CORE_VOLTAGE;
+#include "libhexc.c"
+
+static void
+hexminerc_flush_work (struct cgpu_info *hexminerc)
+{
+    struct hexminerc_info *info = hexminerc->device_data;
+    cgsem_post(&info->qsem);
+}
+
+static int
+hexminerc_send_task (struct hexminerc_task *ht, struct cgpu_info *hexminerc)
+{
+    unsigned char buf[HEXMINERC_TASK_SIZE + 6];
+    int ret, amount = 0;
+    struct hexminerc_info *info;
+    size_t nr_len = HEXMINERC_TASK_SIZE + 6;
+    uint16_t workqueue_adr = htole16 (HEXC_WORKQUEUE_ADR);
+    buf[0] = 0x53;
+    buf[2] = 0x57;                /* Write Command - char 'W' (0x57) */
+    info = hexminerc->device_data;
+    libhexc_generateclk (info->frequency, HEXC_DEFAULT_XCLKIN_CLOCK,
+                         (uint32_t *) & ht->clockcfg[0]);
+    libhexc_setvoltage (info->core_voltage, &ht->refvoltage);
+    ht->chipcount = htole16 (info->asic_count);
+    ht->hashclock = htole16 ((uint16_t) info->frequency);
+    ht->startnonce = 0x00000000;
+    memcpy (buf + 5, ht, HEXMINERC_TASK_SIZE);
+    /* Count Words */
+    buf[1] = (uint8_t) ((HEXMINERC_TASK_SIZE) / 2);
+    memcpy (buf + 3, &workqueue_adr, 2);
+    libhexc_csum (buf, buf + HEXMINERC_TASK_SIZE + 5,
+                  buf + HEXMINERC_TASK_SIZE + 5);
+    if (info->wr_status != HEXC_STAT_IDLE)
+        return nr_len;
+        
+    
+	//applog(LOG_DEBUG, "%s%d: Delaying start by %dms",
+		//	hexminerc->drv->name, hexminerc->device_id, wait / 1000);
+		//if(info->start_up) cgsleep_ms(hexminerc->device_id * HEXC_MAX_START_DELAY_MS);
+    ret = libhexc_sendHashData (hexminerc, buf, nr_len);
+    if (ret != nr_len) {
+        libhexc_reset (hexminerc);
+        mutex_lock (&info->lock);
+        info->usb_w_errors++;
+        mutex_unlock (&info->lock);
+        return -1;
+    }
+    if (info->reset_work) {
+        mutex_lock (&info->lock);
+        //info->start_up  = false;
+        info->reset_work = false;
+        mutex_unlock (&info->lock);
+    }
+    return ret;
+}
+
+static inline void
+hexminerc_create_task (bool reset_work, struct hexminerc_task *ht, struct work *work)
+{
+    if (reset_work) {
+        ht->status = HEXC_STAT_NEW_WORK_CLEAR_OLD;
+    } else {
+        ht->status = HEXC_STAT_NEW_WORK;
+    }
+    memcpy (ht->midstate, work->midstate, 32);
+    memcpy (ht->merkle, work->data + 64, 12);
+    ht->id = (uint8_t) work->subid;
+    libhexc_calc_hexminer (work, ht);
+}
+
+static void *
+hexminerc_send_tasks (void *userdata)
+{
+    struct cgpu_info *hexminerc = (struct cgpu_info *) userdata;
+    struct hexminerc_info *info = hexminerc->device_data;
+    int64_t us_timeout;
+    char threadname[24];
+    snprintf (threadname, 24, "hexc_send/%d", hexminerc->device_id);
+    RenameThread (threadname);
+    libhexc_reset (hexminerc);
+    while(!libhexc_usb_dead(hexminerc)) {
+        int start_count, end_count, ret;
+        cgtimer_t ts_start;
+        struct hexminerc_task ht;
+        cgsleep_prepare_r (&ts_start);
+        us_timeout =
+            0x100000000ll / info->asic_count / info->frequency *
+            HEXMINERC_WORK_FACTOR;
+        mutex_lock (&info->lock);
+        start_count = info->read_pos;
+        end_count =
+            info->read_pos + MIN (info->cg_queue_cached_works,
+                                  HEXMINERC_ARRAY_MAX_POP);
+        while (info->read_pos < HEXMINERC_ARRAY_SIZE_REAL && info->hexworks[info->read_pos] != NULL &&
+               start_count < end_count && info->wr_status == HEXC_STAT_IDLE) {
+            hexminerc_create_task (info->reset_work, &ht, info->hexworks[info->read_pos++]);
+            info->cg_queue_cached_works--;
+            mutex_unlock (&info->lock);
+            ret = hexminerc_send_task (&ht, hexminerc);
+            mutex_lock (&info->lock);
+            start_count++;
+        }
+        mutex_unlock (&info->lock);
+        cgsem_post(&info->qsem);
+        cgsleep_us_r (&ts_start, us_timeout);
+    }
+    pthread_exit (NULL);
+}
+
+static struct cgpu_info
+*hexminerc_detect_one (libusb_device * dev, struct usb_find_devices *found)
+{
+    int miner_count, asic_count, frequency;
+    int this_option_offset = ++option_offset;
+    struct hexminerc_info *info;
+    struct cgpu_info *hexminerc;
+    bool configured;
+    int i = 0;
+    hexminerc = usb_alloc_cgpu (&hexminerc_drv, HEXC_MINER_THREADS);
+    if (!usb_init (hexminerc, dev, found)) {
+        usb_uninit(hexminerc);
+        return NULL;
+    }
+    hexminerc->device_data = calloc (sizeof (struct hexminerc_info), 1);
+    if (unlikely (!(hexminerc->device_data))) {
+        hexminerc->device_data = NULL;
+        usb_uninit(hexminerc);
+        return NULL;
+    }
+    configured =
+        libhexc_get_options (this_option_offset, &asic_count, &frequency);
+    if (opt_hexminerc_core_voltage < HEXC_MIN_COREMV
+        || opt_hexminerc_core_voltage > HEXC_MAX_COREMV) {
+        applog
+        (LOG_ERR,
+         "Invalid hexminerc-voltage %d must be %dmV - %dmV",
+         opt_hexminerc_core_voltage, HEXC_MIN_COREMV, HEXC_MAX_COREMV);
+        free(hexminerc->device_data);
+        hexminerc->device_data = NULL;
+        usb_uninit(hexminerc);
+        return NULL;
+    }
+    info = hexminerc->device_data;
+    info->hexworks = calloc (sizeof (struct work *), HEXMINERC_ARRAY_SIZE);
+    if (unlikely (!(info->hexworks))) {
+        free(hexminerc->device_data);
+        hexminerc->device_data = NULL;
+        usb_uninit(hexminerc);
+        return NULL;
+    }
+    while (i < HEXMINERC_ARRAY_SIZE) info->hexworks[i++] = NULL;
+    //info->start_up = true;
+    info->reset_work = true;
+    info->read_pos = 0;
+    info->write_pos = 0;
+    info->cg_queue_cached_works = 0;
+    info->wr_status = HEXC_STAT_IDLE;
+    info->miner_count = HEXC_DEFAULT_MINER_NUM;
+    info->asic_count = HEXC_DEFAULT_ASIC_NUM;
+    info->frequency = HEXC_DEFAULT_FREQUENCY;
+    info->pic_voltage_readings = HEXC_DEFAULT_CORE_VOLTAGE;
+    info->core_voltage = opt_hexminerc_core_voltage;
+    if (configured) {
+        info->asic_count = asic_count;
+        info->frequency = frequency;
+    }
+    if (!add_cgpu (hexminerc)) {
+        free(info->hexworks);
+        free(hexminerc->device_data);
+        hexminerc->device_data = NULL;
+        hexminerc = usb_free_cgpu (hexminerc);
+        usb_uninit(hexminerc);
+        return NULL;
+    }
+    libhexc_generatenrange_new ((unsigned char *) &info->nonces_range,
+                                info->asic_count);
+    return hexminerc;
+}
+
+static void
+hexminerc_detect (bool __maybe_unused hotplug)
+{
+    usb_detect (&hexminerc_drv, hexminerc_detect_one);
+}
+
+static void
+do_hexminerc_close (struct thr_info *thr)
+{
+    struct cgpu_info *hexminerc = thr->cgpu;
+    struct hexminerc_info *info = hexminerc->device_data;
+    int i = 0;
+    pthread_join (info->read_thr, NULL);
+    pthread_join (info->write_thr, NULL);
+    pthread_mutex_destroy (&info->lock);
+    cgsem_destroy(&info->qsem);
+    while (i < HEXMINERC_ARRAY_SIZE) {
+        if(info->hexworks[i] != NULL) free_work(info->hexworks[i]);
+        i++;
+    }
+    free (info->hexworks);
+    //Hotplug Story
+    //free (hexminerc->device_data);
+    //hexminerc->device_data = NULL;
+    //thr->cgpu = usb_free_cgpu(hexminerc);
+}
+
+static void
+hexminerc_shutdown (struct thr_info *thr)
+{
+    struct cgpu_info *hexminerc = thr->cgpu;
+    struct hexminerc_info *info = hexminerc->device_data;
+    if (!hexminerc->shutdown) hexminerc->shutdown = true;
+    cgsem_post(&info->qsem);
+    do_hexminerc_close (thr);
+}
+
+static void *
+hexminerc_get_results (void *userdata)
+{
+    struct cgpu_info *hexminerc = (struct cgpu_info *) userdata;
+    struct hexminerc_info *info = hexminerc->device_data;
+    unsigned char readbuf[HEXC_HASH_BUF_SIZE];
+    struct workc_result *wr;
+    struct chip_resultsc *array_nonce_cache;
+    struct thr_info *thr = info->thr;
+    int i, lastchippos;
+    int usb_r_reset = 0;
+    int found;
+    uint32_t nonce;
+    char threadname[24];
+    int ret_r = 0, hash_read_pos = 0, hash_write_pos = 0, amount = 0;
+    wr = (struct workc_result *) malloc (sizeof (struct workc_result));
+    array_nonce_cache = calloc (16, sizeof (struct chip_resultsc));
+    int need_work_reset = 0;
+    bzero(array_nonce_cache, 16 * sizeof (struct chip_resultsc));
+    bzero(wr, sizeof (struct workc_result));
+    snprintf (threadname, 24, "hexc_recv/%d", hexminerc->device_id);
+    RenameThread (threadname);
+    while(!libhexc_usb_dead(hexminerc)) {
+        found = true;
+        cgtimer_t ts_start;
+        cgsleep_prepare_r (&ts_start);
+        /* Rotate */
+        ret_r = 0;
+        if (hash_write_pos + HEXC_USB_R_SIZE >= HEXC_HASH_BUF_SIZE) {
+            hash_write_pos = hash_write_pos - hash_read_pos;
+            memcpy (readbuf, readbuf + hash_read_pos, hash_write_pos);
+            hash_read_pos = 0;
+        }
+        if (hash_write_pos - hash_read_pos >= HEXC_BASE_WORK_SIZE + 2) {
+again:
+            ret_r =
+                libhexc_eatHashData (wr, readbuf, &hash_read_pos,
+                                     &hash_write_pos);
+            if (ret_r == 1 && wr->status < HEXC_STAT_UNUSED) {
+                mutex_lock (&info->lock);
+                info->wr_status = wr->status;
+                mutex_unlock (&info->lock);
+            } else {
+                goto out;
+            }
+            if (wr->address != HEXC_WORKANSWER_ADR)
+                goto out;
+            if (wr->lastnonceid > HEXMINERC_ARRAY_SIZE_REAL ) {
+                wr->lastnonceid = 0;
+                need_work_reset++;
+            } else {
+                need_work_reset = 0;
+            }
+            found = 0;
+            nonce = htole32(wr->lastnonce);
+            i = 0;
+            while (i < info->asic_count) {
+                if (nonce < info->nonces_range[++i]) {
+                    lastchippos = --i;
+                    break;
+                }
+            }
+            if (i == info->asic_count)
+                lastchippos = info->asic_count - 1;
+            if (libhexc_cachenonce
+                (&array_nonce_cache[lastchippos], nonce) || need_work_reset < HEXC_USB_R_BAD_ID) {
+                uint8_t work_id = wr->lastnonceid;
+                found+=hexminerc_predecode_nonce (hexminerc, thr, nonce,
+                                                  work_id);
+                if (found>0) {
+                    mutex_lock (&info->lock);
+                    if(info->nonces == 0) libhexc_getvoltage (htole16 (wr->lastvoltage),
+                                &info->pic_voltage_readings);
+                    info->nonces+=found;
+                    info->matching_work[lastchippos]++;
+                    mutex_unlock (&info->lock);
+                } else {
+                    inc_hw_errors (thr);
+                }
+            } else {
+                mutex_lock (&info->lock);
+                info->dupe[lastchippos]++;
+                info->reset_work = true;
+                info->dev_reset_count++;
+                mutex_unlock (&info->lock);
+            }
+out:
+            if (ret_r == 2) {
+                mutex_lock (&info->lock);
+                info->usb_r_errors++;
+                mutex_unlock (&info->lock);
+            }
+            if (hash_write_pos - hash_read_pos > HEXC_MAX_WORK_SIZE)
+                goto again;
+        }
+        ret_r = libhexc_readHashData (hexminerc, readbuf, &hash_write_pos, HEXMINERC_BULK_READ_TIMEOUT, true);
+        if (ret_r != LIBUSB_SUCCESS) {
+            usb_r_reset++;
+            if(usb_r_reset > HEXC_USB_RES_THRESH) {
+                libhexc_reset (hexminerc);
+                usb_r_reset = 0;
+            }
+        } else {
+            usb_r_reset = 0;
+        }
+        // if(libhexc_usb_dead(hexminerc)) break;
+        cgsleep_us_r (&ts_start, HEXMINERC_READ_TIMEOUT);
+    }
+    free (wr);
+    free (array_nonce_cache);
+    pthread_exit (NULL);
+}
+
+static bool
+hexminerc_prepare (struct thr_info *thr)
+{
+    struct cgpu_info *hexminerc = thr->cgpu;
+    struct hexminerc_info *info = hexminerc->device_data;
+    info->thr = thr;
+    mutex_init (&info->lock);
+    cgsem_init(&info->qsem);
+    if (pthread_create
+        (&info->write_thr, NULL, hexminerc_send_tasks, (void *) hexminerc))
+        quit (1, "Failed to create hexminerc write_thr");
+    if (pthread_create
+        (&info->read_thr, NULL, hexminerc_get_results, (void *) hexminerc))
+        quit (1, "Failed to create hexminerc read_thr");
+    return true;
+}
+
+static int64_t
+hexminerc_scanhash (struct thr_info *thr)
+{
+    struct cgpu_info *hexminerc = thr->cgpu;
+    struct hexminerc_info *info = hexminerc->device_data;
+    struct work *work = NULL;
+    int64_t ms_timeout;
+    int64_t hash_count = 0;
+    if(thr->work_restart) goto res;
+    /* 200 ms */
+    ms_timeout = 200;
+    mutex_lock (&info->lock);
+    /* Rotate buffer */
+    if (info->read_pos >= HEXMINERC_ARRAY_SIZE_REAL
+        && info->write_pos >= HEXMINERC_ARRAY_SIZE_REAL ) {
+        info->write_pos = 0;
+        info->read_pos = 0;
+        info->cg_queue_cached_works = 0;
+    }
+    while(!(info->cg_queue_cached_works > HEXMINERC_PUSH_THRESH ||
+            info->write_pos >= HEXMINERC_ARRAY_SIZE_REAL)) {
+        mutex_unlock (&info->lock);
+        work = get_work(thr, thr->id);
+        mutex_lock (&info->lock);
+        if (work == NULL) break;
+        work->subid = info->write_pos;
+        if(info->hexworks[info->write_pos]!=NULL) free_work(info->hexworks[info->write_pos]);
+        info->hexworks[info->write_pos++] = work;
+        info->cg_queue_cached_works++;
+    }
+    hash_count = 0xffffffffull * (uint64_t) info->nonces;
+    info->nonces = 0;
+    mutex_unlock (&info->lock);
+    cgsem_mswait(&info->qsem, ms_timeout);
+res:
+    if (libhexc_usb_dead(hexminerc)) {
+        if(!hexminerc->shutdown) hexminerc->shutdown = true;
+        return -1;
+    }
+    if(thr->work_restart) {
+        mutex_lock (&info->lock);
+        info->reset_work = true;
+        /* Eat Buffer */
+        info->read_pos = 0;
+        info->write_pos = 0;
+        info->cg_queue_cached_works = 0;
+        mutex_unlock (&info->lock);
+    }
+    return hash_count;
+}
+
+static void
+get_hexminerc_statline_before (char *buf, size_t bufsiz,
+                               struct cgpu_info *hexminerc)
+{
+    struct hexminerc_info *info = hexminerc->device_data;
+    tailsprintf (buf, bufsiz, "%3d %4d/%4dmV | ", info->frequency,
+                 info->core_voltage, info->pic_voltage_readings);
+}
+
+static struct api_data *
+hexminerc_api_stats (struct cgpu_info *cgpu) {
+    struct api_data *root = NULL;
+    struct hexminerc_info *info = cgpu->device_data;
+    uint64_t dh64, dr64;
+    double dev_runtime;
+    struct timeval now;
+    int i;
+    char displayed_hashes[16], displayed_rolling[16];
+    double hwp =
+        (cgpu->hw_errors +
+         cgpu->diff1) ? (double) (cgpu->hw_errors) / (double) (cgpu->hw_errors +
+                 cgpu->diff1) : 0;
+    if (cgpu->dev_start_tv.tv_sec == 0)
+        dev_runtime = total_secs;
+    else {
+        cgtime (&now);
+        dev_runtime = tdiff (&now, &(cgpu->dev_start_tv));
+    }
+    if (dev_runtime < 1.0)
+        dev_runtime = 1.0;
+    dh64 = (double) cgpu->total_mhashes / dev_runtime * 1000000ull;
+    dr64 = (double) cgpu->rolling * 1000000ull;
+    suffix_string (dh64, displayed_hashes, sizeof (displayed_hashes), 4);
+    suffix_string (dr64, displayed_rolling, sizeof (displayed_rolling), 4);
+    root = api_add_string (root, "MHS 5s", displayed_rolling, true);
+    root = api_add_string (root, "MHS av", displayed_hashes, true);
+    root = api_add_int (root, "Hardware Errors", &(cgpu->hw_errors), false);
+    root = api_add_percent (root, "Hardware Errors%", &hwp, true);
+    root = api_add_int (root, "USB Read Errors", &(info->usb_r_errors), false);
+    root = api_add_int (root, "USB Write Errors", &(info->usb_w_errors), false);
+    root = api_add_int (root, "Idled for 60 sec", &(info->idled), false);
+    root = api_add_int (root, "Reset Count", &(info->dev_reset_count), false);
+    root =
+        api_add_time (root, "Last Share Time", &(cgpu->last_share_pool_time),
+                      false);
+    root = api_add_int (root, "Chip Count", &(info->asic_count), false);
+    root = api_add_int (root, "Frequency", &(info->frequency), false);
+    root = api_add_int (root, "Core Voltage", &(info->core_voltage), false);
+    root =
+        api_add_int (root, "PIC Voltage Readings", &(info->pic_voltage_readings),
+                     false);
+    for (i = 0; i < info->asic_count; i++) {
+        /*~ */
+        char mcw[24];
+        /*~ */
+        sprintf (mcw, "Chip%d Nonces", i + 1);
+        root = api_add_int (root, mcw, &(info->matching_work[i]), false);
+        sprintf (mcw, "Chip%d Dupes", i + 1);
+        root = api_add_int (root, mcw, &(info->dupe[i]), false);
+    }
+    return root;
+}
+
+static bool hexminerc_thread_init(struct thr_info *thr)
+{
+	struct cgpu_info *hexminerc = thr->cgpu;
+	unsigned int wait;
+
+	/* Pause each new thread at least 100ms between initialising
+	 * so the devices aren't making calls all at the same time. */
+	wait = thr->id * HEXC_MAX_START_DELAY_MS;
+	//applog(LOG_DEBUG, "%s%d: Delaying start by %dms",
+		//	hexminerc->drv->name, hexminerc->device_id, wait / 1000);
+	cgsleep_ms(wait);
+
+	return true;
+}
+
+struct device_drv hexminerc_drv = {
+    .drv_id = DRIVER_hexminerc,
+    .dname = "hexminerc",
+    .name = "HEXc",
+    .drv_detect = hexminerc_detect,
+    .thread_prepare = hexminerc_prepare,
+    //.thread_init = hexminerc_thread_init,
+    .hash_work = hash_queued_work,
+    .scanwork = hexminerc_scanhash,
+    .flush_work = hexminerc_flush_work,
+    .get_api_stats = hexminerc_api_stats,
+    .get_statline_before = get_hexminerc_statline_before,
+    .thread_shutdown = hexminerc_shutdown,
+};
--- cg_o/driver-hexminerc.h	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/driver-hexminerc.h	2013-11-26 09:34:57.148117824 +0200
@@ -0,0 +1,159 @@
+/*$T indentinput.h GC 1.140 10/16/13 10:20:01 */
+
+/*
+ * Copyright 2013 Avalon project Copyright 2013 Con Kolivas <kernel@kolivas.org>
+ * 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. Thank you guy
+ */
+#ifndef HEXC_H
+#define HEXC_H
+
+#ifdef USE_HEXMINERC
+#include "util.h"
+
+/* hexminerc_task/work_reply status Definitions: */
+#define HEXC_STAT_IDLE					0       /* Idle or data already Sent to the buffer */
+#define HEXC_STAT_NEW_WORK				1       /* Request for write in the buffer */
+#define HEXC_STAT_WAITING				2       /* Wait For Buffer Empty Position */
+#define HEXC_STAT_CLR_BUFF				3       /* Force Buffer Empty */
+#define HEXC_STAT_STOP_REQ				4       /* Stop Request */
+#define HEXC_STAT_NEW_WORK_CLEAR_OLD		5       /* Clear Buffers and after that fill the first buffer */
+#define HEXC_STAT_UNUSED					6
+
+#define HEXC_USB_RES_THRESH				7000 //about 1 sec 
+#define HEXC_DEFAULT_XCLKIN_CLOCK		32      /* In MHz */
+#define HEXC_CLOCK_LOW_CFG				0x00030017
+#define HEXC_CLOCK_HIGH_CFG				(0x0000002e << 3)       /* = 0x00000170 */
+#define HEXMINERC_ARRAY_PIC_SIZE		64
+#define HEXMINERC_ARRAY_SIZE			HEXMINERC_ARRAY_PIC_SIZE * 4
+#define HEXMINERC_ARRAY_SIZE_REAL	HEXMINERC_ARRAY_SIZE - 2
+#define HEXC_NONCE_CASH_SIZE				2
+#define HEXMINERC_WORK_FACTOR		0.90    /* We need to be aggressive and fill PIC faster than time taken for a job
+                                                 * to finish. After pic is full we are going to keep that way and leave no
+                                                 * room for potential usb issues timeout:) */
+#define HEXMINERC_PUSH_THRESH		4       /* At least 3 queued works available to be written to PIC */
+#define HEXMINERC_ARRAY_MAX_POP		1
+#define HEXC_USB_R_SIZE					64
+//#define MAX_REPL_PACKET					0x0f
+#define HEXC_USB_R_BAD_ID					32
+#define HEXC_USB_WR_SIZE					64
+#define HEXC_HASH_BUF_SIZE				2048*2
+#define HEXC_USB_WR_TIME_OUT				0
+#define HEXMINERC_READ_TIMEOUT		1000 * 5
+#define HEXMINERC_BULK_READ_TIMEOUT		0
+#define HEXC_MAX_START_DELAY_MS			1000
+#define HEXC_MINER_THREADS			1
+#define HEXC_DEFAULT_MINER_NUM		0x01
+#define HEXC_DEFAULT_ASIC_NUM		0x10
+#define HEXC_MIN_FREQUENCY			100
+#define HEXC_MAX_FREQUENCY			2500
+#define HEXC_DEFAULT_FREQUENCY		1500
+#define HEXC_DEFAULT_CORE_VOLTAGE	1100    /* in millivolts */
+#define HEXC_MIN_COREMV				100    /* in millivolts */
+
+/* Do not touch it!!! 1.6V is above the chip specs already */
+#define HEXC_MAX_COREMV	1630    /* in millivolts */
+
+struct chip_resultsc
+{
+  uint8_t nonce_cache_write_pos;
+  uint32_t nonces[HEXC_NONCE_CASH_SIZE];
+};
+
+struct workc_result
+{
+  uint8_t startbyte;
+  uint8_t datalength;
+  uint8_t command;
+  uint16_t address;
+  uint32_t lastnonce;
+  uint8_t lastnonceid;
+  uint8_t status;
+  uint16_t lastvoltage;
+  uint16_t lasttemperature;
+  uint16_t lastfanrpm;
+  uint32_t serial;
+  uint16_t openloadduty;
+  uint16_t workingduty;
+  uint16_t lastworkingduty;
+  uint16_t clockforce;          /* Times Avalons Crashed */
+  uint8_t pad[3];
+} __attribute__ ((packed, aligned (4)));
+
+struct hexminerc_info
+{
+  int miner_count;
+  int asic_count;
+  int core_voltage;
+  int frequency;
+  int idled;
+  int nonces;
+  int read_pos;
+  int write_pos;
+  int usb_r_errors;
+  int usb_w_errors;
+  int dev_reset_count;
+  int pic_voltage_readings;
+  int64_t usb_timing;
+  int cg_queue_cached_works;
+  int dupe[HEXC_DEFAULT_ASIC_NUM];
+  int matching_work[HEXC_DEFAULT_ASIC_NUM];
+  //bool flagnewblock;
+  bool reset_work;
+  bool start_up;
+  uint8_t wr_status;
+  uint8_t wr_lastnonceid;
+  uint32_t nonces_range[HEXC_DEFAULT_ASIC_NUM];
+  pthread_t read_thr;
+  pthread_t write_thr;
+  pthread_mutex_t lock;
+  cgsem_t qsem;
+  struct thr_info *thr;
+  struct work **hexworks;
+};
+
+
+/*
+ -----------------------------------------------------------------------------------------------------------------------
+    2 + 3 + 1 + 1 + 1 + 1 + 1 + 8 + 1 + 1 + 1 + 2 = 23(uint32_t)=46(uint16_t)=
+ -----------------------------------------------------------------------------------------------------------------------
+ */
+struct hexminerc_task
+{
+  uint32_t clockcfg[2];
+  uint32_t merkle[3];
+  uint32_t a1;
+  uint32_t a0;
+  uint32_t e2;
+  uint32_t e1;
+  uint32_t e0;
+  uint8_t midstate[32];
+  uint32_t a2;
+  uint32_t startnonce;
+  uint8_t id;
+  uint8_t status;
+  uint16_t hashclock;
+  uint16_t chipcount;
+  uint16_t refvoltage;
+  uint16_t reftemperature;
+  uint16_t reffanrpm;
+} __attribute__ ((packed, aligned (4)));
+
+#define HEXC_WORKANSWER_ADR	0x3000
+#define HEXC_WORKQUEUE_ADR	0x4000
+#define HEXC_PTCON_ADR		0x0C00
+#define HEXC_START_STOP_ADR	0x646E
+#define HEXMINERC_TASK_SIZE	(sizeof(struct hexminerc_task))
+#define HEXC_MAX_WORK_SIZE		(sizeof(struct workc_result) - 3)
+#define HEXC_BASE_WORK_SIZE		6       /* Min uint8_t startbyte + uint8_t datalength + uint8_t command + uint16_t
+                                         * address;
+                                         * + uint8_t csum */
+
+extern int opt_hexminerc_core_voltage;
+extern char *libhexc_set_config_voltage (char *arg);
+extern struct hexminerc_info **hexminerc_info;
+#endif /* USE_HEXMINERC */
+#endif /* HEXC_H */
--- cg_o/libhexc.c	1970-01-01 02:00:00.000000000 +0200
+++ cgminer/libhexc.c	2013-11-26 09:34:57.148117824 +0200
@@ -0,0 +1,388 @@
+/*$T indentinput.c GC 1.140 10/16/13 10:20:34 */
+#define rotate(x, y)	((x << y) | (x >> (sizeof(x) * 8 - y)))
+#define rotr(x, y)		((x >> y) | (x << (sizeof(x) * 8 - y)))
+#define R(a, b, c, d, e, f, g, h, w, k) \
+		h = h + \
+		(rotate(e, 26) ^ rotate(e, 21) ^ rotate(e, 7)) + \
+		(g ^ (e & (f ^ g))) + \
+		k + \
+		w; \
+	d = d + h; \
+	h = h + (rotate(a, 30) ^ rotate(a, 19) ^ rotate(a, 10)) + ((a & b) | (c & (a | b)))
+extern const uint32_t SHA256_K[64];
+
+static bool
+libhexc_cachenonce (struct chip_resultsc *nonce_cache, uint32_t nonce)
+{
+  int i = 0;
+  while (i < HEXC_NONCE_CASH_SIZE && nonce_cache->nonces[i] != nonce)
+    i++;
+  if (i < HEXC_NONCE_CASH_SIZE)
+    return false;
+  //Rotate
+  if (nonce_cache->nonce_cache_write_pos == HEXC_NONCE_CASH_SIZE)
+    nonce_cache->nonce_cache_write_pos = 0;
+  nonce_cache->nonces[nonce_cache->nonce_cache_write_pos++] = nonce;
+  return true;
+}
+
+static void
+libhexc_generatenrange_new (unsigned char *buf, int asic_num)
+{
+  uint32_t nonceAdd;
+  int noncePos;
+  int64_t nonceCalc = 0x100000000ll;
+  nonceCalc /= asic_num;
+  nonceAdd = (uint32_t) nonceCalc;
+  uint32_t chip_noce;
+  for (noncePos = 0; noncePos < asic_num; noncePos++)
+    {
+      /*
+       * chip_noce = htole32(noncePos * nonceAdd);
+       */
+      chip_noce = noncePos * nonceAdd;
+      memcpy (buf + noncePos * 4, &chip_noce, 4);
+    }
+}
+
+char *
+libhexc_set_config_voltage (char *arg)
+{
+  int val1, ret;
+  ret = sscanf (arg, "%d", &val1);
+  if (ret < 1)
+    return "No values passed to hexminerc-voltage";
+  if (val1 < HEXC_MIN_COREMV || val1 > HEXC_MAX_COREMV)
+    return "Invalid value passed to hexminerc-voltage";
+  opt_hexminerc_core_voltage = val1;
+  return NULL;
+}
+/*
+    Thanks to BkkCoins & devileraser!
+ */
+
+static void
+libhexc_calc_hexminer (struct work *work, struct hexminerc_task *ht)
+{
+  uint32_t a0a1a2e0e1e2[6];
+  uint32_t A, B, C, D, E, F, G, H, T;
+  uint32_t state[8];
+  uint32_t data[3];
+  memcpy (&state, work->midstate, 32);
+  memcpy (&data, work->data + 64, 12);
+#if defined(__BIG_ENDIAN__) || defined(MIPSEB)
+  int i;
+  for (i = 0; i < 8; i++)
+    state[i] = htole32 (state[i]);
+  for (i = 0; i < 3; i++)
+    data[i] = htole32 (data[i]);
+#endif
+  A = state[0];
+  B = state[1];
+  C = state[2];
+  D = state[3];
+  E = state[4];
+  F = state[5];
+  G = state[6];
+  H = state[7];
+  R (A, B, C, D, E, F, G, H, data[0], SHA256_K[0]);
+  a0a1a2e0e1e2[0] = htole32 (H);
+  a0a1a2e0e1e2[3] = htole32 (D);
+  R (H, A, B, C, D, E, F, G, data[1], SHA256_K[1]);
+  a0a1a2e0e1e2[1] = htole32 (G);
+  a0a1a2e0e1e2[4] = htole32 (C);
+  R (G, H, A, B, C, D, E, F, data[2], SHA256_K[2]);
+  a0a1a2e0e1e2[2] = htole32 (F);
+  a0a1a2e0e1e2[5] = htole32 (B);
+  memcpy (&ht->a0, &a0a1a2e0e1e2[0], 4);
+  memcpy (&ht->a1, &a0a1a2e0e1e2[1], 4);
+  memcpy (&ht->a2, &a0a1a2e0e1e2[2], 4);
+  memcpy (&ht->e0, &a0a1a2e0e1e2[3], 4);
+  memcpy (&ht->e1, &a0a1a2e0e1e2[4], 4);
+  memcpy (&ht->e2, &a0a1a2e0e1e2[5], 4);
+}
+/*
+    From Hexminer core developer Thanks!
+ */
+
+static void
+libhexc_generateclk (uint16_t HashClock, uint16_t XCLKIN, uint32_t * res)
+{
+  uint32_t configL = 0;
+  uint32_t configH = 0;
+  int RValue = XCLKIN;
+  int NValue = (HashClock * 2 * RValue / XCLKIN);
+  configL =
+    ((uint32_t) RValue << 29) | ((uint32_t) NValue << 18) |
+    HEXC_CLOCK_LOW_CFG;
+  configH = ((uint32_t) RValue >> 3) | HEXC_CLOCK_HIGH_CFG;
+  res[0] = htole32 (configL);
+  res[1] = htole32 (configH);
+}
+
+static void
+libhexc_csum (unsigned char *startptr, unsigned char *endptr,
+              unsigned char *resptr)
+{
+  unsigned char *b = startptr;
+  uint8_t sum = 0;
+  while (b < endptr)
+    sum += *b++;
+  memcpy (resptr, &sum, 1);
+}
+
+static bool
+libhexc_get_options (int this_option_offset, int *asic_count, int *frequency)
+{
+  char buf[BUFSIZ + 1];
+  char *ptr, *comma, *colon, *colon2, *colon3, *colon4;
+  bool timeout_default;
+  size_t max;
+  int i, tmp;
+  if (opt_hexminerc_options == NULL)
+    buf[0] = '\0';
+  else
+    {
+      ptr = opt_hexminerc_options;
+      for (i = 0; i < this_option_offset; i++)
+        {
+          comma = strchr (ptr, ',');
+          if (comma == NULL)
+            break;
+          ptr = comma + 1;
+        }
+      comma = strchr (ptr, ',');
+      if (comma == NULL)
+        max = strlen (ptr);
+      else
+        max = comma - ptr;
+      if (max > BUFSIZ)
+        max = BUFSIZ;
+      strncpy (buf, ptr, max);
+      buf[max] = '\0';
+    }
+  if (!(*buf))
+    return false;
+  colon = strchr (buf, ':');
+  if (colon)
+    *(colon++) = '\0';
+  tmp = atoi (buf);
+  if (tmp > 0 && tmp <= HEXC_DEFAULT_ASIC_NUM)
+    *asic_count = tmp;
+  else
+    {
+      quit (1,
+            "Invalid hexminerc-options for " "asic_count (%s) must be 1 ~ %d",
+            buf, HEXC_DEFAULT_ASIC_NUM);
+    }
+  if (colon && *colon)
+    {
+      tmp = atoi (colon);
+      if (tmp < HEXC_MIN_FREQUENCY || tmp > HEXC_MAX_FREQUENCY)
+        {
+          quit
+            (1,
+             "Invalid hexminerc-options for frequency (%s) must be %d <= frequency <= %d",
+             colon, HEXC_MIN_FREQUENCY, HEXC_MAX_FREQUENCY);
+        }
+      *frequency = tmp;
+    }
+  return true;
+}
+
+static bool
+libhexc_usb_dead (struct cgpu_info *hexminerc)
+{
+  struct cg_usb_device *usbdev;
+  usbdev = hexminerc->usbdev;
+  return (usbdev == NULL
+          || usbdev->handle == NULL
+          || hexminerc->shutdown
+          || hexminerc->usbinfo.nodev || hexminerc->deven != DEV_ENABLED);
+}
+
+static int
+libhexc_sendHashData (struct cgpu_info *hexminerc, unsigned char *sendbuf,
+                      size_t buf_len)
+{
+  struct hexminerc_info *info = hexminerc->device_data;
+  struct cg_usb_device *usbdev;
+  int wrote = 0, written = 0;
+  int err = LIBUSB_SUCCESS;
+  int pstate;
+  usb_lock_w (hexminerc, pstate);
+  usbdev = hexminerc->usbdev;
+  if (libhexc_usb_dead (hexminerc))
+    goto out;
+  while (written < buf_len && err == LIBUSB_SUCCESS)
+    {
+      err = libusb_bulk_transfer
+        (usbdev->handle,
+         0x02,
+         sendbuf + written,
+         MIN (HEXC_USB_WR_SIZE, buf_len - written), &wrote,
+         HEXC_USB_WR_TIME_OUT);
+      if (err == LIBUSB_SUCCESS)
+        written += wrote;
+    }
+out:
+  usb_unlock_w (hexminerc, pstate);
+  return written;
+}
+
+static void
+libhexc_reset (struct cgpu_info *hexminerc)
+{
+  struct hexminerc_info *info = hexminerc->device_data;
+  struct cg_usb_device *usbdev;
+  int err = LIBUSB_SUCCESS;
+  int pstate;
+  usb_lock_w (hexminerc, pstate);
+  usbdev = hexminerc->usbdev;
+  if (libhexc_usb_dead (hexminerc))
+    goto out;
+  err = libusb_reset_device (usbdev->handle);
+out:
+  usb_unlock_w (hexminerc, pstate);
+}
+
+static int libhexc_readHashData
+  (struct cgpu_info *hexminerc,
+   unsigned char *hash, int *hash_write_pos, int timeout, bool read_once)
+{
+  struct hexminerc_info *info = hexminerc->device_data;
+  struct cg_usb_device *usbdev;
+  int read = 0, total = 0;
+  int err = LIBUSB_SUCCESS;
+  int pstate;
+  usb_lock_r (hexminerc, pstate);
+  usbdev = hexminerc->usbdev;
+  if (libhexc_usb_dead (hexminerc))
+    goto out;
+  while (*hash_write_pos + HEXC_USB_R_SIZE < HEXC_HASH_BUF_SIZE
+         && err == LIBUSB_SUCCESS)
+    {
+      err =
+        libusb_bulk_transfer (usbdev->handle, 0x82, hash + *hash_write_pos,
+                              HEXC_USB_R_SIZE, &read, timeout);
+      if (err == LIBUSB_SUCCESS)
+        {
+          *hash_write_pos += read;
+          total += read;
+        }
+      if (read_once)
+        break;
+    }
+out:
+  usb_unlock_r (hexminerc, pstate);
+  if (err == LIBUSB_ERROR_NO_DEVICE || err == LIBUSB_ERROR_NOT_FOUND)
+    {
+      hexminerc->shutdown = true;
+      cgsem_post (&info->qsem);
+    }
+  return err;
+}
+
+static int
+hexminerc_predecode_nonce (struct cgpu_info *hexminerc, struct thr_info *thr,
+                           uint32_t nonce, uint8_t work_id)
+{
+  struct hexminerc_info *info = hexminerc->device_data;
+  int res = 0;
+  mutex_lock (&info->lock);
+  if (info->hexworks[work_id] == NULL)
+    goto out;
+  if (test_nonce (info->hexworks[work_id], nonce))
+    {
+      submit_tested_work (thr, info->hexworks[work_id]);
+      res = 1;
+    }
+out:
+  mutex_unlock (&info->lock);
+  return res;
+}
+/*
+    From Hexminer core developer Thanks!
+ */
+
+static void
+libhexc_getvoltage (uint16_t wr_bukvoltage, int *info_pic_voltage_readings)
+{
+  float voltagehuman;
+  voltagehuman =
+    (float) ((float) wr_bukvoltage * (float) 1000 * (float) 3.3 /
+             ((1 << 12) - 1));
+  *info_pic_voltage_readings = (int) voltagehuman;
+}
+/*
+    From Hexminer core developer Thanks!
+ */
+
+static void
+libhexc_setvoltage (int info_voltage, uint16_t * refvoltage)
+{
+  uint16_t voltageadc;
+  voltageadc =
+    (uint16_t) ((float) info_voltage / (float) 1000 / (float) 3.3 *
+                ((1 << 12) - 1));
+  *refvoltage = htole16 (voltageadc);
+}
+
+static int
+libhexc_eatHashData (struct workc_result *wr, unsigned char *hash,
+                     int *hash_read_pos, int *hash_write_pos)
+{
+  uint8_t psum;
+  int wrpos;
+  unsigned char *csum_pos;
+  bool ok;
+eat:
+  while (*hash_read_pos < *hash_write_pos && hash[*hash_read_pos] != 0x53)
+    {
+      *hash_read_pos += 1;
+    }
+  if (*hash_write_pos - *hash_read_pos < HEXC_BASE_WORK_SIZE)
+    goto done;
+  memcpy ((char *) &wr->startbyte, &hash[*hash_read_pos],
+          HEXC_BASE_WORK_SIZE - 1);
+  wr->address = htole16 (wr->address);
+  /* Address is outside be strict to avoid mem corruption - not fancy but it works */
+  ok = (wr->command == 0x52) &&
+    ((wr->address == HEXC_WORKANSWER_ADR && wr->datalength == 0x06)
+     || (wr->address == HEXC_WORKANSWER_ADR + 4 && wr->datalength == 1));
+  if (!ok)
+    {
+      *hash_read_pos += 1;
+      goto eat;
+    }
+  if (*hash_write_pos - *hash_read_pos <
+      HEXC_BASE_WORK_SIZE + wr->datalength * 2)
+    goto done;
+  csum_pos =
+    hash + *hash_read_pos + HEXC_BASE_WORK_SIZE + wr->datalength * 2 - 1;
+  //Crap?
+  if (csum_pos - hash < HEXC_HASH_BUF_SIZE)
+    {
+      //That was writing somewhere and corrupting memory because of faulty usb reads....
+      libhexc_csum (hash + *hash_read_pos, csum_pos, &psum);
+      if (psum != *csum_pos)
+        {
+          *hash_read_pos += 1;
+          return 2;
+        }
+    }
+  else
+    {
+      *hash_read_pos += 1;
+      return 2;
+    }
+  wrpos = (wr->address - HEXC_WORKANSWER_ADR) + HEXC_BASE_WORK_SIZE - 1;
+  memcpy
+    ((char *) &wr->startbyte + wrpos,
+     &hash[*hash_read_pos + HEXC_BASE_WORK_SIZE - 1],
+     MIN (wr->datalength * 2, HEXC_MAX_WORK_SIZE - HEXC_BASE_WORK_SIZE - 1));
+  *hash_read_pos += HEXC_BASE_WORK_SIZE + wr->datalength * 2;
+  return 1;
+done:
+  return 0;
+}
