diff --git a/ASIC-README b/ASIC-README index a56666cb..f495d29f 100644 --- a/ASIC-README +++ b/ASIC-README @@ -105,7 +105,7 @@ ASIC SPECIFIC COMMANDS --bitburner-fury-options Override avalon-options for BitBurner Fury boards baud:miners:asic:timeout:freq --bitburner-fury-voltage Set BitBurner Fury core voltage, in millivolts --bitburner-voltage Set BitBurner (Avalon) core voltage, in millivolts ---klondike-options Set klondike options clock:temp1:temp2:fan +--klondike-options Set klondike options clock:temptarget AVALON AND BITBURNER DEVICES diff --git a/README b/README index 0a96dee1..7f327940 100644 --- a/README +++ b/README @@ -227,6 +227,7 @@ ASIC only options: --bitburner-fury-options Override avalon-options for BitBurner Fury boards baud:miners:asic:timeout:freq --bitburner-fury-voltage Set BitBurner Fury core voltage, in millivolts --bitburner-voltage Set BitBurner (Avalon) core voltage, in millivolts +--klondike-options Set klondike options clock:temptarget See ASIC-README for more information regarding these. diff --git a/cgminer.c b/cgminer.c index cfcf5144..8a1f4b7f 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1274,7 +1274,7 @@ static struct opt_table opt_config_table[] = { #ifdef USE_KLONDIKE OPT_WITH_ARG("--klondike-options", set_klondike_options, NULL, NULL, - "Set klondike options clock:temp1:temp2:fan"), + "Set klondike options clock:temptarget"), #endif OPT_WITHOUT_ARG("--load-balance", set_loadbalance, &pool_strategy, @@ -4030,51 +4030,20 @@ static int block_sort(struct block *blocka, struct block *blockb) return blocka->block_no - blockb->block_no; } +/* Decode the current block difficulty which is in packed form */ static void set_blockdiff(const struct work *work) { - uint64_t *data64, d64, diff64; - double previous_diff; - uint32_t diffhash[8]; - uint32_t difficulty; - uint32_t diffbytes; - uint32_t diffvalue; - char rhash[32]; - int diffshift; - - difficulty = swab32(*((uint32_t *)(work->data + 72))); - - diffbytes = ((difficulty >> 24) & 0xff) - 3; - diffvalue = difficulty & 0x00ffffff; - - diffshift = (diffbytes % 4) * 8; - if (diffshift == 0) { - diffshift = 32; - diffbytes--; - } - - memset(diffhash, 0, 32); - diffbytes >>= 2; - if (unlikely(diffbytes > 6)) - return; - diffhash[diffbytes + 1] = diffvalue >> (32 - diffshift); - diffhash[diffbytes] = diffvalue << diffshift; - - swab256(rhash, diffhash); - - if (opt_scrypt) - data64 = (uint64_t *)(rhash + 2); - else - data64 = (uint64_t *)(rhash + 4); - d64 = bswap_64(*data64); - if (unlikely(!d64)) - d64 = 1; + uint8_t pow = work->data[72]; + int powdiff = (8 * (0x1d - 3)) - (8 * (pow - 3)); + uint32_t diff32 = swab32(*((uint32_t *)(work->data + 72))) & 0x00FFFFFF; + double numerator = 0xFFFFULL << powdiff; + double ddiff = numerator / (double)diff32; - previous_diff = current_diff; - diff64 = diffone / d64; - suffix_string(diff64, block_diff, sizeof(block_diff), 0); - current_diff = (double)diffone / (double)d64; - if (unlikely(current_diff != previous_diff)) + if (unlikely(current_diff != ddiff)) { + suffix_string(ddiff, block_diff, sizeof(block_diff), 0); + current_diff = ddiff; applog(LOG_NOTICE, "Network diff set to %s", block_diff); + } } static bool test_work_current(struct work *work) @@ -5929,38 +5898,23 @@ static void gen_hash(unsigned char *data, unsigned char *hash, int len) sha256(hash1, 32, hash); } -/* Diff 1 is a 256 bit unsigned integer of - * 0x00000000ffff0000000000000000000000000000000000000000000000000000 - * so we use a big endian 64 bit unsigned integer centred on the 5th byte to - * cover a huge range of difficulty targets, though not all 256 bits' worth */ void set_target(unsigned char *dest_target, double diff) { - unsigned char target[32]; + unsigned char target[32], rtarget[32]; uint64_t *data64, h64; double d64; - d64 = diffone; + if (opt_scrypt) + d64 = 0xFFFF00000000ull; + else + d64 = 0xFFFF0000ull; d64 /= diff; h64 = d64; - memset(target, 0, 32); - if (h64) { - unsigned char rtarget[32]; - - memset(rtarget, 0, 32); - if (opt_scrypt) - data64 = (uint64_t *)(rtarget + 2); - else - data64 = (uint64_t *)(rtarget + 4); - *data64 = htobe64(h64); - swab256(target, rtarget); - } else { - /* Support for the classic all FFs just-below-1 diff */ - if (opt_scrypt) - memset(target, 0xff, 30); - else - memset(target, 0xff, 28); - } + memset(rtarget, 0xFF, 32); + data64 = (uint64_t *)rtarget; + *data64 = htobe64(h64); + swab256(target, rtarget); if (opt_debug) { char *htarget = bin2hex(target, 32); @@ -6145,6 +6099,14 @@ static void update_work_stats(struct thr_info *thr, struct work *work) { work->share_diff = share_diff(work); + if (unlikely(work->share_diff >= current_diff)) { + work->block = true; + work->pool->solved++; + found_blocks++; + work->mandatory = true; + applog(LOG_NOTICE, "Found block for pool %d!", work->pool->pool_no); + } + mutex_lock(&stats_lock); total_diff1 += work->device_diff; thr->cgpu->diff1 += work->device_diff; diff --git a/driver-klondike.c b/driver-klondike.c index dcdd671c..54743d64 100644 --- a/driver-klondike.c +++ b/driver-klondike.c @@ -63,9 +63,6 @@ static const char *msg_reply = "Reply"; #define KLN_KILLWORK_TEMP 53.5 #define KLN_COOLED_DOWN 45.5 -// If 5 late updates in a row, try to reset the device -#define KLN_LATE_UPDATE_LIMIT 5 - /* * Work older than 5s will already be completed * FYI it must not be possible to complete 256 work @@ -74,12 +71,29 @@ static const char *msg_reply = "Reply"; */ #define OLD_WORK_MS ((int)(5 * 1000)) +/* + * How many incorrect slave counts to ignore in a row + * 2 means it allows random grabage returned twice + * Until slaves are implemented, this should never occur + * so allowing 2 in a row should ignore random errros + */ +#define KLN_ISS_IGNORE 2 + /* * If the queue status hasn't been updated for this long then do it now * 5GH/s = 859ms per full nonce range */ #define LATE_UPDATE_MS ((int)(2.5 * 1000)) +// If 5 late updates in a row, try to reset the device +#define LATE_UPDATE_LIMIT 5 + +// If the reset fails sleep for 1s +#define LATE_UPDATE_SLEEP_MS 1000 + +// However give up after 8s +#define LATE_UPDATE_NODEV_MS ((int)(8.0 * 1000)) + struct device_drv klondike_drv; typedef struct klondike_header { @@ -194,12 +208,12 @@ typedef struct jobque { int workqc; struct timeval last_update; bool overheat; + bool flushed; int late_update_count; int late_update_sequential; } JOBQUE; struct klondike_info { - bool shutdown; pthread_rwlock_t stat_lock; struct thr_info replies_thr; cglock_t klist_lock; @@ -216,6 +230,7 @@ struct klondike_info { uint64_t hashcount; uint64_t errorcount; uint64_t noisecount; + int incorrect_slave_sequential; // us Delay from USB reply to being processed double delay_count; @@ -301,7 +316,7 @@ static KLIST *allocate_kitem(struct cgpu_info *klncgpu) cg_wunlock(&klninfo->klist_lock); if (ran_out > 0) - applog(LOG_ERR, "%s", errbuf); + applog(LOG_WARNING, "%s", errbuf); return kitem; } @@ -540,7 +555,7 @@ static KLIST *GetReply(struct cgpu_info *klncgpu, uint8_t cmd, uint8_t dev) KLIST *kitem; int retries = CMD_REPLY_RETRIES; - while (retries-- > 0 && klninfo->shutdown == false) { + while (retries-- > 0 && klncgpu->shutdown == false) { cgsleep_ms(REPLY_WAIT_TIME); cg_rlock(&klninfo->klist_lock); kitem = klninfo->used; @@ -696,16 +711,13 @@ static bool klondike_init(struct cgpu_info *klncgpu) // boundaries are checked by device, with valid values returned if (opt_klondike_options != NULL) { int hashclock; - double temp1, temp2; + double temptarget; - sscanf(opt_klondike_options, "%d:%lf:%lf:%"SCNu8, - &hashclock, - &temp1, &temp2, - &kline.cfg.fantarget); + sscanf(opt_klondike_options, "%d:%lf", &hashclock, &temptarget); SET_HASHCLOCK(kline.cfg.hashclock, hashclock); - kline.cfg.temptarget = cvtCToKln(temp1); - kline.cfg.tempcritical = cvtCToKln(temp2); - kline.cfg.fantarget = (int)255*kline.cfg.fantarget/100; + kline.cfg.temptarget = cvtCToKln(temptarget); + kline.cfg.tempcritical = 0; // hard code for old firmware + kline.cfg.fantarget = 0xff; // hard code for old firmware size = sizeof(kline.cfg) - 2; } @@ -932,13 +944,13 @@ static void *klondike_get_replies(void *userdata) struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); KLIST *kitem = NULL; char *hexdata; - int err, recd, slaves, dev; - bool overheat; + int err, recd, slaves, dev, isc; + bool overheat, sent; applog(LOG_DEBUG, "%s%i: listening for replies", klncgpu->drv->name, klncgpu->device_id); - while (klninfo->shutdown == false) { + while (klncgpu->shutdown == false) { if (klncgpu->usbinfo.nodev) return NULL; @@ -956,7 +968,9 @@ static void *klondike_get_replies(void *userdata) } if (!err && recd == REPLY_SIZE) { cgtime(&(kitem->tv_when)); + rd_lock(&(klninfo->stat_lock)); kitem->block_seq = klninfo->block_seq; + rd_unlock(&(klninfo->stat_lock)); if (opt_log_level <= READ_DEBUG) { hexdata = bin2hex((unsigned char *)&(kitem->kline.hd.dev), recd-1); applog(READ_DEBUG, "%s%i:%d reply [%c:%s]", @@ -993,27 +1007,59 @@ static void *klondike_get_replies(void *userdata) klondike_check_nonce(klncgpu, kitem); display_kline(klncgpu, &kitem->kline, msg_reply); break; - case KLN_CMD_STATUS: case KLN_CMD_WORK: + // We can't do/check this until it's initialised + if (klninfo->initialised) { + dev = kitem->kline.ws.dev; + if (kitem->kline.ws.workqc == 0) { + bool idle = false; + rd_lock(&(klninfo->stat_lock)); + if (klninfo->jobque[dev].flushed == false) + idle = true; + slaves = klninfo->status[0].kline.ws.slavecount; + rd_lock(&(klninfo->stat_lock)); + if (idle) + applog(LOG_WARNING, "%s%i:%d went idle before work was sent", + klncgpu->drv->name, + klncgpu->device_id, + dev); + } + wr_lock(&(klninfo->stat_lock)); + klninfo->jobque[dev].flushed = false; + wr_lock(&(klninfo->stat_lock)); + } + case KLN_CMD_STATUS: case KLN_CMD_ABORT: // We can't do/check this until it's initialised if (klninfo->initialised) { + isc = 0; dev = kitem->kline.ws.dev; wr_lock(&(klninfo->stat_lock)); klninfo->jobque[dev].workqc = (int)(kitem->kline.ws.workqc); cgtime(&(klninfo->jobque[dev].last_update)); slaves = klninfo->status[0].kline.ws.slavecount; overheat = klninfo->jobque[dev].overheat; + if (dev == 0) { + if (kitem->kline.ws.slavecount != slaves) + isc = ++klninfo->incorrect_slave_sequential; + else + isc = klninfo->incorrect_slave_sequential = 0; + } wr_unlock(&(klninfo->stat_lock)); - if (kitem->kline.ws.slavecount != slaves) { - applog(LOG_ERR, "%s%i:%d reply [%c] has a diff # of slaves=%d" - " (curr=%d) dropping device to hotplug", - klncgpu->drv->name, klncgpu->device_id, - dev, (char)(kitem->kline.ws.cmd), + if (isc) { + applog(LOG_ERR, "%s%i:%d reply [%c] has a diff" + " # of slaves=%d (curr=%d)%s", + klncgpu->drv->name, + klncgpu->device_id, + dev, + (char)(kitem->kline.ws.cmd), (int)(kitem->kline.ws.slavecount), - slaves); - klninfo->shutdown = true; + slaves, + isc <= KLN_ISS_IGNORE ? "" : + " disabling device"); + if (isc > KLN_ISS_IGNORE) + usb_nodev(klncgpu); break; } @@ -1026,22 +1072,24 @@ static void *klondike_get_replies(void *userdata) klninfo->jobque[dev].overheat = true; wr_unlock(&(klninfo->stat_lock)); - applog(LOG_ERR, "%s%i:%d Critical overheat (%.0fC)", - klncgpu->drv->name, klncgpu->device_id, - dev, temp); + applog(LOG_WARNING, "%s%i:%d Critical overheat (%.0fC)", + klncgpu->drv->name, + klncgpu->device_id, + dev, temp); zero_kline(&kline); kline.hd.cmd = KLN_CMD_ABORT; kline.hd.dev = dev; - if (!SendCmd(klncgpu, &kline, KSENDHD(0))) { - applog(LOG_ERR, "%s%i:%d failed to abort work" - " - dropping device to hotplug", + sent = SendCmd(klncgpu, &kline, KSENDHD(0)); + kln_disable(klncgpu, dev, false); + if (!sent) { + applog(LOG_ERR, "%s%i:%d overheat failed to" + " abort work - disabling device", klncgpu->drv->name, klncgpu->device_id, dev); - klninfo->shutdown = true; + usb_nodev(klncgpu); } - kln_disable(klncgpu, dev, false); } } } @@ -1080,13 +1128,13 @@ static void klondike_flush_work(struct cgpu_info *klncgpu) KLINE kline; int slaves, dev; + wr_lock(&(klninfo->stat_lock)); klninfo->block_seq++; + slaves = klninfo->status[0].kline.ws.slavecount; + wr_unlock(&(klninfo->stat_lock)); applog(LOG_DEBUG, "%s%i: flushing work", klncgpu->drv->name, klncgpu->device_id); - rd_lock(&(klninfo->stat_lock)); - slaves = klninfo->status[0].kline.ws.slavecount; - rd_unlock(&(klninfo->stat_lock)); zero_kline(&kline); kline.hd.cmd = KLN_CMD_ABORT; for (dev = 0; dev <= slaves; dev++) { @@ -1097,6 +1145,7 @@ static void klondike_flush_work(struct cgpu_info *klncgpu) memcpy((void *)&(klninfo->status[dev]), kitem, sizeof(klninfo->status[dev])); + klninfo->jobque[dev].flushed = true; wr_unlock(&(klninfo->stat_lock)); kitem = release_kitem(klncgpu, kitem); } @@ -1142,7 +1191,7 @@ static void klondike_shutdown(struct thr_info *thr) kln_disable(klncgpu, klninfo->status[0].kline.ws.slavecount, true); - klncgpu->shutdown = klninfo->shutdown = true; + klncgpu->shutdown = true; } static void klondike_thread_enable(struct thr_info *thr) @@ -1228,10 +1277,13 @@ static bool klondike_queue_full(struct cgpu_info *klncgpu) { struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); struct work *work = NULL; - int dev, queued, slaves, seq; + int dev, queued, slaves, seq, howlong; struct timeval now; bool nowork; + if (klncgpu->shutdown == true) + return true; + cgtime(&now); rd_lock(&(klninfo->stat_lock)); slaves = klninfo->status[0].kline.ws.slavecount; @@ -1240,25 +1292,30 @@ static bool klondike_queue_full(struct cgpu_info *klncgpu) klninfo->jobque[dev].late_update_count++; seq = ++klninfo->jobque[dev].late_update_sequential; rd_unlock(&(klninfo->stat_lock)); - if (seq < KLN_LATE_UPDATE_LIMIT) { - applog(LOG_ERR, "%s%i:%d late update", + if (seq < LATE_UPDATE_LIMIT) { + applog(LOG_DEBUG, "%s%i:%d late update", klncgpu->drv->name, klncgpu->device_id, dev); klondike_get_stats(klncgpu); goto que; } else { - applog(LOG_ERR, "%s%i:%d late update (%d) reached - attempting reset", - klncgpu->drv->name, klncgpu->device_id, - dev, KLN_LATE_UPDATE_LIMIT); + applog(LOG_WARNING, "%s%i:%d late update (%d) reached - attempting reset", + klncgpu->drv->name, klncgpu->device_id, + dev, LATE_UPDATE_LIMIT); control_init(klncgpu); kln_enable(klncgpu); klondike_get_stats(klncgpu); rd_lock(&(klninfo->stat_lock)); - if (ms_tdiff(&now, &(klninfo->jobque[dev].last_update)) > LATE_UPDATE_MS) { + howlong = ms_tdiff(&now, &(klninfo->jobque[dev].last_update)); + if (howlong > LATE_UPDATE_MS) { rd_unlock(&(klninfo->stat_lock)); - applog(LOG_ERR, "%s%i:%d reset failed - dropping device", - klncgpu->drv->name, klncgpu->device_id, dev); - klninfo->shutdown = true; - return false; + if (howlong > LATE_UPDATE_NODEV_MS) { + applog(LOG_ERR, "%s%i:%d reset failed - dropping device", + klncgpu->drv->name, klncgpu->device_id, dev); + usb_nodev(klncgpu); + } else + cgsleep_ms(LATE_UPDATE_SLEEP_MS); + + return true; } break; } @@ -1283,9 +1340,9 @@ tryagain: if (temp <= KLN_COOLED_DOWN) { klninfo->jobque[dev].overheat = false; rd_unlock(&(klninfo->stat_lock)); - applog(LOG_ERR, "%s%i:%d Overheat recovered (%.0fC)", - klncgpu->drv->name, klncgpu->device_id, - dev, temp); + applog(LOG_WARNING, "%s%i:%d Overheat recovered (%.0fC)", + klncgpu->drv->name, klncgpu->device_id, + dev, temp); kln_enable(klncgpu); goto tryagain; } else { @@ -1345,6 +1402,7 @@ static int64_t klondike_scanwork(struct thr_info *thr) klninfo->noncecount = 0; rd_unlock(&(klninfo->stat_lock)); } + return newhashcount; } diff --git a/usbutils.c b/usbutils.c index 9851ed55..87789dfe 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1390,6 +1390,20 @@ static void release_cgpu(struct cgpu_info *cgpu) cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); } +/* + * Force a NODEV on a device so it goes back to hotplug + */ +void usb_nodev(struct cgpu_info *cgpu) +{ + int pstate; + + DEVWLOCK(cgpu, pstate); + + release_cgpu(cgpu); + + DEVWUNLOCK(cgpu, pstate); +} + /* * Use the same usbdev thus locking is across all related devices */ @@ -2530,14 +2544,14 @@ int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t cgtimer_t now, already_done; double sleep_estimate; double write_time = (double)(usbdev->last_write_siz) / - (double)(usbdev->cps); + (double)(usbdev->cps) * 1000; cgtimer_time(&now); cgtimer_sub(&now, &usbdev->cgt_last_write, &already_done); sleep_estimate = write_time - cgtimer_to_ms(&already_done); if (sleep_estimate > 0.0) { - cgsleep_ms_r(&usbdev->cgt_last_write, write_time * 1000.0); + cgsleep_ms_r(&usbdev->cgt_last_write, write_time); cgpu->usbinfo.read_delay_count++; cgpu->usbinfo.total_read_delay += sleep_estimate; } @@ -2631,14 +2645,14 @@ int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t cgtimer_t now, already_done; double sleep_estimate; double write_time = (double)(usbdev->last_write_siz) / - (double)(usbdev->cps); + (double)(usbdev->cps) * 1000; cgtimer_time(&now); cgtimer_sub(&now, &usbdev->cgt_last_write, &already_done); sleep_estimate = write_time - cgtimer_to_ms(&already_done); if (sleep_estimate > 0.0) { - cgsleep_ms_r(&usbdev->cgt_last_write, write_time * 1000.0); + cgsleep_ms_r(&usbdev->cgt_last_write, write_time); cgpu->usbinfo.read_delay_count++; cgpu->usbinfo.total_read_delay += sleep_estimate; } @@ -2778,14 +2792,14 @@ int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_ cgtimer_t now, already_done; double sleep_estimate; double write_time = (double)(usbdev->last_write_siz) / - (double)(usbdev->cps); + (double)(usbdev->cps) * 1000; cgtimer_time(&now); cgtimer_sub(&now, &usbdev->cgt_last_write, &already_done); sleep_estimate = write_time - cgtimer_to_ms(&already_done); if (sleep_estimate > 0.0) { - cgsleep_ms_r(&usbdev->cgt_last_write, write_time * 1000.0); + cgsleep_ms_r(&usbdev->cgt_last_write, write_time); cgpu->usbinfo.write_delay_count++; cgpu->usbinfo.total_write_delay += sleep_estimate; } @@ -2917,14 +2931,14 @@ int __usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bReques cgtimer_t now, already_done; double sleep_estimate; double write_time = (double)(usbdev->last_write_siz) / - (double)(usbdev->cps); + (double)(usbdev->cps) * 1000; cgtimer_time(&now); cgtimer_sub(&now, &usbdev->cgt_last_write, &already_done); sleep_estimate = write_time - cgtimer_to_ms(&already_done); if (sleep_estimate > 0.0) { - cgsleep_ms_r(&usbdev->cgt_last_write, write_time * 1000.0); + cgsleep_ms_r(&usbdev->cgt_last_write, write_time); cgpu->usbinfo.write_delay_count++; cgpu->usbinfo.total_write_delay += sleep_estimate; } @@ -2999,14 +3013,14 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe cgtimer_t now, already_done; double sleep_estimate; double write_time = (double)(usbdev->last_write_siz) / - (double)(usbdev->cps); + (double)(usbdev->cps) * 1000; cgtimer_time(&now); cgtimer_sub(&now, &usbdev->cgt_last_write, &already_done); sleep_estimate = write_time - cgtimer_to_ms(&already_done); if (sleep_estimate > 0.0) { - cgsleep_ms_r(&usbdev->cgt_last_write, write_time * 1000.0); + cgsleep_ms_r(&usbdev->cgt_last_write, write_time); cgpu->usbinfo.read_delay_count++; cgpu->usbinfo.total_read_delay += sleep_estimate; } diff --git a/usbutils.h b/usbutils.h index bcf75100..3ef1fa3e 100644 --- a/usbutils.h +++ b/usbutils.h @@ -378,7 +378,8 @@ bool async_usb_transfers(void); void cancel_usb_transfers(void); void usb_all(int level); const char *usb_cmdname(enum usb_cmds cmd); -void usb_applog(struct cgpu_info *bflsc, enum usb_cmds cmd, char *msg, int amount, int err); +void usb_applog(struct cgpu_info *cgpu, enum usb_cmds cmd, char *msg, int amount, int err); +void usb_nodev(struct cgpu_info *cgpu); struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig); struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads); struct cgpu_info *usb_free_cgpu(struct cgpu_info *cgpu); diff --git a/util.c b/util.c index 363c73c4..d3d2897f 100644 --- a/util.c +++ b/util.c @@ -588,10 +588,13 @@ char *get_proxy(char *url, struct pool *pool) void __bin2hex(char *s, const unsigned char *p, size_t len) { int i; + static const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - for (i = 0; i < (int)len; i++) - sprintf(s + (i * 2), "%02x", (unsigned int)p[i]); - + for (i = 0; i < (int)len; i++) { + *s++ = hex[p[i] >> 4]; + *s++ = hex[p[i] & 0xF]; + } + *s++ = '\0'; } /* Returns a malloced array string of a binary value of arbitrary length. The @@ -615,33 +618,48 @@ char *bin2hex(const unsigned char *p, size_t len) } /* Does the reverse of bin2hex but does not allocate any ram */ +static const int hex2bin_tbl[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; bool hex2bin(unsigned char *p, const char *hexstr, size_t len) { + int nibble1, nibble2; + unsigned char idx; bool ret = false; while (*hexstr && len) { - char hex_byte[4]; - unsigned int v; - if (unlikely(!hexstr[1])) { applog(LOG_ERR, "hex2bin str truncated"); return ret; } - memset(hex_byte, 0, 4); - hex_byte[0] = hexstr[0]; - hex_byte[1] = hexstr[1]; + idx = *hexstr++; + nibble1 = hex2bin_tbl[idx]; + idx = *hexstr++; + nibble2 = hex2bin_tbl[idx]; - if (unlikely(sscanf(hex_byte, "%x", &v) != 1)) { - applog(LOG_INFO, "hex2bin sscanf '%s' failed", hex_byte); + if (unlikely((nibble1 < 0) || (nibble2 < 0))) { + applog(LOG_ERR, "hex2bin scan failed"); return ret; } - *p = (unsigned char) v; - - p++; - hexstr += 2; - len--; + *p++ = (((unsigned char)nibble1) << 4) | ((unsigned char)nibble2); + --len; } if (likely(len == 0 && *hexstr == 0)) @@ -1061,9 +1079,13 @@ void cgtimer_time(cgtimer_t *ts_start) static void liSleep(LARGE_INTEGER *li, int timeout) { - HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL); + HANDLE hTimer; DWORD ret; + if (unlikely(timeout <= 0)) + return; + + hTimer = CreateWaitableTimer(NULL, TRUE, NULL); if (unlikely(!hTimer)) quit(1, "Failed to create hTimer in liSleep"); ret = SetWaitableTimer(hTimer, li, 0, NULL, NULL, 0);