<html><head></head><body><div style="font-family: Verdana;font-size: 12.0px;"><div># HG changeset patch<br/>
# User Michael Wagner <michael.wagner@gmx.at><br/>
# Date 1474015004 -7200<br/>
# Fri Sep 16 10:36:44 2016 +0200<br/>
# Node ID d6ee4a5066611703778f4b341b0c8b3d5c51e1b4<br/>
# Parent a1b8b53606f6025fc1ad727331837cfc7759f178<br/>
[btech] Delayed retry on writing to radio in case of errornous response. Needed mostly on linux. Fixes issue #3993<br/>
If radio responds with the infamous '0x05', driver now retries, but delays after each sent byte. Happens mostly on linux, and on several radios of this family (found on a KT-8900R).<br/>
Might also affect/fix also #3587 and #3635.<br/>
Many Thanks to Pavel Milanes for his support (analysis, explainations of the driver, sharing his knowledge about this and similar bugs, helping me with python-codestyle), and for encouraging me to contribute this patch.</div>
<div><br/>
Michael Wagner,<br/>
OE4AMW<br/>
<br/>
diff -r a1b8b53606f6 -r d6ee4a506661 chirp/drivers/btech.py<br/>
--- a/chirp/drivers/btech.py Sat Sep 10 11:34:01 2016 -0400<br/>
+++ b/chirp/drivers/btech.py Fri Sep 16 10:36:44 2016 +0200<br/>
@@ -21,6 +21,7 @@<br/>
<br/>
LOG = logging.getLogger(__name__)<br/>
<br/>
+from time import sleep<br/>
from chirp import chirp_common, directory, memmap<br/>
from chirp import bitwise, errors, util<br/>
from chirp.settings import RadioSettingGroup, RadioSetting, \<br/>
@@ -236,7 +237,7 @@<br/>
<br/>
# this var controls the verbosity in the debug and by default it's low (False)<br/>
# make it True and you will to get a very verbose debug.log<br/>
-debug = False<br/>
+debug = True<br/>
<br/>
# Power Levels<br/>
NORMAL_POWER_LEVELS = [chirp_common.PowerLevel("High", watts=25),<br/>
@@ -334,6 +335,9 @@<br/>
# magic string for all other models<br/>
MSTRING = "\x55\x20\x15\x09\x20\x45\x4d\x02"<br/>
<br/>
+# this variables controls the forced delay and retry on Linux OS mainly. Added by OE4AMW to workaround Issue 3993<br/>
+NEEDS_DELAY = False<br/>
+RETRY_DELAYED = False<br/>
<br/>
def _clean_buffer(radio):<br/>
"""Cleaning the read serial buffer, hard timeout to survive an infinite<br/>
@@ -383,6 +387,11 @@<br/>
if len(data) < amount:<br/>
LOG.warn("Short reading %d bytes from the %d requested." %<br/>
(len(data), amount))<br/>
+ # This problem can be and expression of the MCU getting stuck<br/>
+ # so from now own we must delay the write operations.<br/>
+ global NEEDS_DELAY<br/>
+ NEEDS_DELAY = True<br/>
+ LOG.debug("Delaying future writes.")<br/>
<br/>
except:<br/>
raise errors.RadioError("Error reading data from radio")<br/>
@@ -396,11 +405,26 @@<br/>
try:<br/>
for byte in data:<br/>
radio.pipe.write(byte)<br/>
+ # Some OS (mainly Linux ones) are two fast on the serial and<br/>
+ # get the MCU inside the radio stuck in the early stages, this<br/>
+ # hits some models more than others.<br/>
+ #<br/>
+ # To cope with that we introduce a delay on the writes but only if<br/>
+ # we detect this problem, this was found by Michael Wagner who<br/>
+ # proposed a patch for it, well done.<br/>
+ if NEEDS_DELAY:<br/>
+ # 10 msec is proved to be safe, is better to be slow and right<br/>
+ # than fast and some times wrong. (5 msec is tested ok)<br/>
+ sleep(0.010)<br/>
<br/>
# DEBUG<br/>
if debug is True:<br/>
+ if NEEDS_DELAY:<br/>
+ LOG.debug("This write was delayed")<br/>
+<br/>
LOG.debug("==> (%d) bytes:\n\n%s" %<br/>
(len(data), util.hexprint(data)))<br/>
+<br/>
except:<br/>
raise errors.RadioError("Error sending data to radio")<br/>
<br/>
@@ -435,9 +459,21 @@<br/>
# header validation<br/>
c, a, l = struct.unpack(">BHB", block[1:5])<br/>
if a != addr or l != BLOCK_SIZE or c != ord("X"):<br/>
- LOG.debug("Invalid header for block 0x%04x" % addr)<br/>
+ LOG.error("Invalid header for block 0x%04x" % addr)<br/>
LOG.debug("CMD: %s ADDR: %04x SIZE: %02x" % (c, a, l))<br/>
- raise errors.RadioError("Invalid header for block 0x%04x:" % addr)<br/>
+<br/>
+ global RETRY_DELAYED<br/>
+ if not RETRY_DELAYED:<br/>
+ # first try with header problems, forcing a write delay<br/>
+ LOG.warn("Failure occured, trying once again with delay")<br/>
+ RETRY_DELAYED = True<br/>
+ global NEEDS_DELAY<br/>
+ NEEDS_DELAY = True<br/>
+ return False<br/>
+ else:<br/>
+ # second try, now we fail.<br/>
+ LOG.debug("This was already a retry")<br/>
+ raise errors.RadioError("Invalid header for block 0x%04x:" % addr)<br/>
<br/>
# return the data<br/>
return block[5:]<br/>
@@ -613,6 +649,16 @@<br/>
# read<br/>
d = _recv(radio, addr)<br/>
<br/>
+ if d == False:<br/>
+ # retry to get that block of data.<br/>
+ msg = "Previous block request failed."<br/>
+ msg += " Cleaning buffer and trying again."<br/>
+ LOG.info(msg)<br/>
+ _clean_buffer(radio)<br/>
+ d = _recv(radio, addr)<br/>
+ global RETRY_DELAYED<br/>
+ RETRY_DELAYED = False<br/>
+<br/>
# aggregate the data<br/>
data += d<br/>
<br/>
@@ -821,7 +867,16 @@<br/>
<br/>
def sync_in(self):<br/>
"""Download from radio"""<br/>
- data = _download(self)<br/>
+ try:<br/>
+ data = _download(self)<br/>
+ except errors.RadioError:<br/>
+ msg = "First download-attempt failed."<br/>
+ msg += " Retrying the whole procedure with delayed writes."<br/>
+ LOG.error(msg)<br/>
+ global NEEDS_DELAY<br/>
+ NEEDS_DELAY = True<br/>
+ data = _download(self)<br/>
+<br/>
self._mmap = memmap.MemoryMap(data)<br/>
self.process_mmap()<br/>
<br/>
@@ -1284,7 +1339,7 @@<br/>
if self.MODEL in ("UV-2501", "UV-5001"):<br/>
vfomren = RadioSetting("settings2.vfomren", "VFO/MR switching",<br/>
RadioSettingValueBoolean(<br/>
- _mem.settings2.vfomren))<br/>
+ not _mem.settings2.vfomren))<br/>
advanced.append(vfomren)<br/>
<br/>
reseten = RadioSetting("settings2.reseten", "RESET",<br/>
@@ -1569,6 +1624,8 @@<br/>
if element.has_apply_callback():<br/>
LOG.debug("Using apply callback")<br/>
element.run_apply_callback()<br/>
+ elif setting == "vfomren":<br/>
+ setattr(obj, setting, not int(element.value))<br/>
elif element.value.get_mutable():<br/>
LOG.debug("Setting %s = %s" % (setting, element.value))<br/>
setattr(obj, setting, element.value)</div></div></body></html>