# HG changeset patch # User Jim Unroe rock.unroe@gmail.com # Date 1491143983 14400 # Node ID 0714032989d2d0ea7fa82c231e4ab374835375b4 # Parent 6ad4b478463019b1a1af7a0f7e7b3e7083994988 [UV-5R] "Incorrect 'Model' selected." error
When Baofeng started shipping tri-power radios back in 2014, the firmware version format could be used to identify if the detected radio had 2 power levels (HIGH/LOW) or 3 power levels (HIGH/MID/LOW). CHIRP would then use this firmware version to not only determine if the user had selected the correct radio model, but also to present the only settings that were available on the selected model.
Recently Baofeng radio models with 3 power levels have been shipping with with the HN5RV001 firmware version. This same firmware version, as it has for the last 2 years, continues to ship in radio models that have only 2 power levels. This firmware version defeats CHIRP's ability to differentiate on its own between these two model types.
This patch addresses the problem in 2 ways.
1. for radios with the HN5RV001 firmware version, CHIRP will assume that the user has selected the correct radio model. The selected model is then appended to the end of the image so CHIRP can identify the radio model when image is loaded back into CHIRP at a later time.
2. the driver will now selectively uploads the image in ranges, thus bypassing specific areas of memory that must not be overwritten by images from radios with a different firmware version.
This patch also addresses, in a similar way, a related problem where the radio does not report a firmware version at all to CHIRP.
releated to issue #4445 and many others
diff -r 6ad4b4784630 -r 0714032989d2 chirp/drivers/uv5r.py --- a/chirp/drivers/uv5r.py Thu Mar 30 12:47:43 2017 -0700 +++ b/chirp/drivers/uv5r.py Sun Apr 02 10:39:43 2017 -0400 @@ -282,7 +282,7 @@
BASETYPE_UV5R = ["BFS", "BFB", "N5R-2", "N5R2", "N5RV", "BTS", "D5R2"] BASETYPE_F11 = ["USA"] -BASETYPE_UV82 = ["US2S", "B82S", "BF82", "N82-2", "N822"] +BASETYPE_UV82 = ["US2S2", "B82S", "BF82", "N82-2", "N822"] BASETYPE_BJ55 = ["BJ55"] # needed for for the Baojie UV-55 in bjuv55.py BASETYPE_UV6 = ["BF1", "UV6"] BASETYPE_KT980HP = ["BFP3V3 B"] @@ -544,8 +544,29 @@ radio_version = _get_radio_firmware_version(radio) LOG.info("Radio Version is %s" % repr(radio_version))
- if not any(type in radio_version for type in radio._basetype): + if "HN5RV" in radio_version: + # A radio with HN5RV firmware has been detected. It could be a + # UV-5R style radio with HIGH/LOW power levels or it could be a + # BF-F8HP style radio with HIGH/MID/LOW power levels. + # We are going to count on the user to make the right choice and + # then append that model type to the end of the image so it can + # be properly detected when loaded. + append_model = True + elif "\xFF" * 14 in radio_version: + # A radio UV-5R style radio that reports no firmware version has + # been detected. + # We are going to count on the user to make the right choice and + # then append that model type to the end of the image so it can + # be properly detected when loaded. + append_model = True + elif not any(type in radio_version for type in radio._basetype): + # This radio can't be properly detected by parsing its firmware + # version. raise errors.RadioError("Incorrect 'Model' selected.") + else: + # This radio can be properly detected by parsing its firmware version. + # There is no need to append its model type to the end of the image. + append_model = False
# Main block LOG.debug("downloading main block...") @@ -558,6 +579,10 @@ # Auxiliary block starts at 0x1ECO (?) for i in range(0x1EC0, 0x2000, 0x40): data += _read_block(radio, i, 0x40, False) + + if append_model: + data += radio.MODEL.ljust(8) + LOG.debug("done.") return memmap.MemoryMap(data)
@@ -586,34 +611,68 @@ LOG.info("Image Version is %s" % repr(image_version)) LOG.info("Radio Version is %s" % repr(radio_version))
- if image_version != radio_version: + # default ranges + _ranges_main_default = [ + (0x0008, 0x0CF8), + (0x0D08, 0x0DF8), + (0x0E08, 0x1808) + ] + _ranges_aux_default = [ + (0x1EC0, 0x1EF0), + ] + + # extra aux ranges + _ranges_aux_extra = [ + (0x1F60, 0x1F70), + (0x1F80, 0x1F90), + (0x1FC0, 0x1FD0) + ] + + if image_version == radio_version: + image_matched_radio = True + if image_version.startswith("HN5RV"): + ranges_main = _ranges_main_default + ranges_aux = _ranges_aux_default + _ranges_aux_extra + elif image_version == 0xFF * 14: + ranges_main = _ranges_main_default + ranges_aux = _ranges_aux_default + _ranges_aux_extra + else: + ranges_main = radio._ranges_main + ranges_aux = radio._ranges_aux + elif any(type in radio_version for type in radio._basetype): + image_matched_radio = False + ranges_main = _ranges_main_default + ranges_aux = _ranges_aux_default + else: msg = ("The upload was stopped because the firmware " "version of the image (%s) does not match that " "of the radio (%s).") raise errors.RadioError(msg % (image_version, radio_version))
# Main block - for i in range(0x08, 0x1808, 0x10): - _send_block(radio, i - 0x08, radio.get_mmap()[i:i + 0x10]) - _do_status(radio, i) - _do_status(radio, radio.get_memsize()) + for start_addr, end_addr in ranges_main: + for i in range(start_addr, end_addr, 0x10): + _send_block(radio, i - 0x08, radio.get_mmap()[i:i + 0x10]) + _do_status(radio, i) + _do_status(radio, radio.get_memsize())
if len(radio.get_mmap().get_packed()) == 0x1808: LOG.info("Old image, not writing aux block") return # Old image, no aux block
- if image_version != radio_version: + # Auxiliary block at radio address 0x1EC0, our offset 0x1808 + for start_addr, end_addr in ranges_aux: + for i in range(start_addr, end_addr, 0x10): + addr = 0x1808 + (i - 0x1EC0) + _send_block(radio, i, radio.get_mmap()[addr:addr + 0x10]) + + if image_matched_radio == False: msg = ("Upload finished, but the 'Other Settings' " "could not be sent because the firmware " "version of the image (%s) does not match " "that of the radio (%s).") raise errors.RadioError(msg % (image_version, radio_version))
- # Auxiliary block at radio address 0x1EC0, our offset 0x1808 - for i in range(0x1EC0, 0x2000, 0x10): - addr = 0x1808 + (i - 0x1EC0) - _send_block(radio, i, radio.get_mmap()[addr:addr + 0x10]) - UV5R_POWER_LEVELS = [chirp_common.PowerLevel("High", watts=4.00), chirp_common.PowerLevel("Low", watts=1.00)]
@@ -627,6 +686,20 @@ "!@#$%^&*()+-=[]:";'<>?,./"
+def model_match(cls, data): + """Match the opened/downloaded image to the correct version""" + + if len(data) == 0x1950: + rid = data[0x1948:0x1950] + return rid.startswith(cls.MODEL) + elif len(data) == 0x1948: + rid = data[cls._fw_ver_file_start:cls._fw_ver_file_stop] + if any(type in rid for type in cls._basetype): + return True + else: + return False + + class BaofengUV5R(chirp_common.CloneModeRadio, chirp_common.ExperimentalRadio):
@@ -649,6 +722,13 @@ _fw_ver_file_start = 0x1838 _fw_ver_file_stop = 0x1846
+ _ranges_main = [ + (0x0008, 0x1808), + ] + _ranges_aux = [ + (0x1EC0, 0x2000), + ] + @classmethod def get_prompts(cls): rp = chirp_common.RadioPrompts() @@ -709,13 +789,10 @@ def match_model(cls, filedata, filename): match_size = False match_model = False - if len(filedata) in [0x1808, 0x1948]: + if len(filedata) in [0x1808, 0x1948, 0x1950]: match_size = True - fwdata = _firmware_version_from_data(filedata, - cls._fw_ver_file_start, - cls._fw_ver_file_stop) - if any(type in fwdata for type in cls._basetype): - match_model = True + match_model = model_match(cls, filedata) + if match_size and match_model: return True else: @@ -1189,8 +1266,9 @@
if self.MODEL == "UV-82HP": # this is a UV-82HP only feature - rs = RadioSetting("vfomrlock", "VFO/MR Switching", - RadioSettingValueBoolean(_settings.vfomrlock)) + rs = RadioSetting( + "vfomrlock", "VFO/MR Switching (BTech UV-82HP only)", + RadioSettingValueBoolean(_settings.vfomrlock)) advanced.append(rs)
if self.MODEL == "UV-82": @@ -1201,15 +1279,15 @@
if self.MODEL == "UV-82HP": # this is an UV-82HP only feature - rs = RadioSetting("singleptt", "Single PTT", + rs = RadioSetting("singleptt", "Single PTT (BTech UV-82HP only)", RadioSettingValueBoolean(_settings.singleptt)) advanced.append(rs)
if self.MODEL == "UV-82HP": # this is an UV-82HP only feature - rs = RadioSetting("tdrch", "Tone Burst Frequency", - RadioSettingValueList( - RTONE_LIST, RTONE_LIST[_settings.tdrch])) + rs = RadioSetting( + "tdrch", "Tone Burst Frequency (BTech UV-82HP only)", + RadioSettingValueList(RTONE_LIST, RTONE_LIST[_settings.tdrch])) advanced.append(rs)
if len(self._mmap.get_packed()) == 0x1808: