<html><head></head><body><div style="font-family: Verdana;font-size: 12.0px;"><div># HG changeset patch<br/>
# User Michael Wagner &lt;michael.wagner@gmx.at&gt;<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 &#39;0x05&#39;, 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, &#92;<br/>
@@ -236,7 +237,7 @@<br/>
<br/>
# this var controls the verbosity in the debug and by default it&#39;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(&quot;High&quot;, watts=25),<br/>
@@ -334,6 +335,9 @@<br/>
# magic string for all other models<br/>
MSTRING = &quot;&#92;x55&#92;x20&#92;x15&#92;x09&#92;x20&#92;x45&#92;x4d&#92;x02&quot;<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/>
&quot;&quot;&quot;Cleaning the read serial buffer, hard timeout to survive an infinite<br/>
@@ -383,6 +387,11 @@<br/>
if len(data) &lt; amount:<br/>
LOG.warn(&quot;Short reading %d bytes from the %d requested.&quot; %<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(&quot;Delaying future writes.&quot;)<br/>
<br/>
except:<br/>
raise errors.RadioError(&quot;Error reading data from radio&quot;)<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(&quot;This write was delayed&quot;)<br/>
+<br/>
LOG.debug(&quot;==&gt; (%d) bytes:&#92;n&#92;n%s&quot; %<br/>
(len(data), util.hexprint(data)))<br/>
+<br/>
except:<br/>
raise errors.RadioError(&quot;Error sending data to radio&quot;)<br/>
<br/>
@@ -435,9 +459,21 @@<br/>
# header validation<br/>
c, a, l = struct.unpack(&quot;&gt;BHB&quot;, block[1:5])<br/>
if a != addr or l != BLOCK_SIZE or c != ord(&quot;X&quot;):<br/>
- LOG.debug(&quot;Invalid header for block 0x%04x&quot; % addr)<br/>
+ LOG.error(&quot;Invalid header for block 0x%04x&quot; % addr)<br/>
LOG.debug(&quot;CMD: %s ADDR: %04x SIZE: %02x&quot; % (c, a, l))<br/>
- raise errors.RadioError(&quot;Invalid header for block 0x%04x:&quot; % addr)<br/>
+<br/>
+ global RETRY_DELAYED<br/>
+ if not RETRY_DELAYED:<br/>
+ # first try with header problems, forcing a write delay<br/>
+ LOG.warn(&quot;Failure occured, trying once again with delay&quot;)<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(&quot;This was already a retry&quot;)<br/>
+ raise errors.RadioError(&quot;Invalid header for block 0x%04x:&quot; % 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 = &quot;Previous block request failed.&quot;<br/>
+ msg += &quot; Cleaning buffer and trying again.&quot;<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/>
&quot;&quot;&quot;Download from radio&quot;&quot;&quot;<br/>
- data = _download(self)<br/>
+ try:<br/>
+ data = _download(self)<br/>
+ except errors.RadioError:<br/>
+ msg = &quot;First download-attempt failed.&quot;<br/>
+ msg += &quot; Retrying the whole procedure with delayed writes.&quot;<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 (&quot;UV-2501&quot;, &quot;UV-5001&quot;):<br/>
vfomren = RadioSetting(&quot;settings2.vfomren&quot;, &quot;VFO/MR switching&quot;,<br/>
RadioSettingValueBoolean(<br/>
- _mem.settings2.vfomren))<br/>
+ not _mem.settings2.vfomren))<br/>
advanced.append(vfomren)<br/>
<br/>
reseten = RadioSetting(&quot;settings2.reseten&quot;, &quot;RESET&quot;,<br/>
@@ -1569,6 +1624,8 @@<br/>
if element.has_apply_callback():<br/>
LOG.debug(&quot;Using apply callback&quot;)<br/>
element.run_apply_callback()<br/>
+ elif setting == &quot;vfomren&quot;:<br/>
+ setattr(obj, setting, not int(element.value))<br/>
elif element.value.get_mutable():<br/>
LOG.debug(&quot;Setting %s = %s&quot; % (setting, element.value))<br/>
setattr(obj, setting, element.value)</div></div></body></html>