├── .gitignore ├── README.md ├── ab90_reset.py ├── card_programming.py ├── clio3_eps_reset.py ├── clio4_eps_reset.py ├── laguna2_uch_reset.py ├── laguna3_uch_reset.py ├── megane2_uch_reset.py ├── megane3_ab_reset.py ├── megane3_eps_reset.py ├── megane3_uch_reset.py ├── requirements.txt ├── rsat4_reset.py └── vin_crc.py /.gitignore: -------------------------------------------------------------------------------- 1 | /__pycache__/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ddtplugins 2 | -------------------------------------------------------------------------------- /ab90_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | import PyQt5.QtCore as core 6 | import PyQt5.QtWidgets as gui 7 | 8 | import ecu 9 | import options 10 | 11 | _ = options.translator('ddt4all') 12 | 13 | plugin_name = _("AB90 AIRBAG Reset") 14 | category = _("Airbag Tools") 15 | need_hw = True 16 | ecufile = "AB90_J77_X85" 17 | 18 | 19 | class Virginizer(gui.QDialog): 20 | def __init__(self): 21 | super(Virginizer, self).__init__() 22 | self.airbag_ecu = ecu.Ecu_file(ecufile, True) 23 | layout = gui.QVBoxLayout() 24 | infos = gui.QLabel(_("AB90 (Clio III)/2
" 25 | "AIRBAG VIRGINIZER
THIS PLUGIN WILL UNLOCK AIRBAG CRASH DATA
" 26 | "GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 27 | infos.setAlignment(core.Qt.AlignHCenter) 28 | check_button = gui.QPushButton(_("Check ACU Virgin")) 29 | self.status_check = gui.QLabel(_("Waiting")) 30 | self.status_check.setAlignment(core.Qt.AlignHCenter) 31 | self.virginize_button = gui.QPushButton(_("Virginize ACU")) 32 | layout.addWidget(infos) 33 | layout.addWidget(check_button) 34 | layout.addWidget(self.status_check) 35 | layout.addWidget(self.virginize_button) 36 | self.setLayout(layout) 37 | self.virginize_button.setEnabled(True) 38 | self.virginize_button.clicked.connect(self.reset_ecu) 39 | check_button.clicked.connect(self.check_virgin_status) 40 | self.ecu_connect() 41 | 42 | def ecu_connect(self): 43 | connection = self.airbag_ecu.connect_to_hardware() 44 | if not connection: 45 | options.main_window.logview.append(_("Cannot connect to ECU")) 46 | self.finished() 47 | 48 | def check_virgin_status(self): 49 | self.start_diag_session() 50 | 51 | crash_reset_request = self.airbag_ecu.requests[u'Synthèse état UCE'] 52 | values_dict = crash_reset_request.send_request({}, "62 02 04 00 00 00 00 00 00 00 00 00 00 00 00") 53 | 54 | if values_dict is None: 55 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 56 | 57 | crash = values_dict[u'crash détecté'] 58 | 59 | if crash == u'crash détecté': 60 | self.status_check.setText(_("CRASH DETECTED")) 61 | else: 62 | self.status_check.setText(_("NO CRASH DETECTED")) 63 | 64 | def start_diag_session(self): 65 | sds_request = self.airbag_ecu.requests[u"Start Diagnostic Session"] 66 | 67 | sds_stream = " ".join(sds_request.build_data_stream({})) 68 | if options.simulation_mode: 69 | print("SdS stream", sds_stream) 70 | return 71 | options.elm.start_session_can(sds_stream) 72 | 73 | def reset_ecu(self): 74 | self.start_diag_session() 75 | 76 | reset_request = self.airbag_ecu.requests[u"Reset crash ou accès au mode fournisseur"] 77 | request_response = reset_request.send_request({u"code d'accès pour reset UCE": '22041998'}) 78 | 79 | if request_response is not None: 80 | self.status_check.setText(_("CLEAR EXECUTED")) 81 | else: 82 | self.status_check.setText(_("CLEAR FAILED")) 83 | 84 | 85 | def plugin_entry(): 86 | v = Virginizer() 87 | v.exec_() 88 | -------------------------------------------------------------------------------- /card_programming.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Plugin to program keys on Megane II 4 | # (c) 2017 5 | # This is an example plugin 6 | 7 | 8 | import PyQt5.QtCore as core 9 | import PyQt5.QtWidgets as gui 10 | 11 | import ecu 12 | import options 13 | 14 | _ = options.translator('ddt4all') 15 | 16 | plugin_name = _("Megane/Scenic II card programming") 17 | category = _("Keys") 18 | need_hw = True 19 | ecufile = "UCH_84_J84_03_60" 20 | 21 | a8_mess = [19, 29, 39, 4, 24, 46, 31, 12, 22 | 16, 28, 7, 10, 15, 0, 40, 26, 23 | 18, 20, 3, 8, 34, 8, 47, 21, 24 | 2, 25, 38, 6, 4, 22, 14, 33, 25 | 17, 1, 44, 11, 32, 41, 36, 42, 26 | 5, 45, 5, 43, 30, 37, 13, 27] 27 | 28 | a8_xor = [0x10, 0x20, 0x20, 0x10, 0x81, 0x88] 29 | a8_xor_2 = [0x10, 0x20, 0x28, 0x10, 0x81, 0x88] 30 | 31 | 32 | def a8(isk_c): 33 | '''MC9S12DG256 (Megane 2, Scenic 2)''' 34 | apv = '' 35 | isk = isk_c.replace(' ', '').decode('hex') 36 | if len(isk) != 6: 37 | return None 38 | bit_i = '' 39 | for c in isk: 40 | bit_i += bin(ord(c))[2:].zfill(8) 41 | 42 | # if not (bit_i[ 4]!=bit_i[23] and bit_i[12]==bit_i[43] and 43 | # bit_i[ 4]==bit_i[35] and bit_i[ 8]==bit_i[ 9] and bit_i[ 4]==bit_i[ 5]): 44 | # return 'Invalid ISK' 45 | 46 | base = '' 47 | for b in a8_xor: 48 | base = base + bin(b)[2:].zfill(8) 49 | 50 | i = 0 51 | for b in base: 52 | z = bit_i[a8_mess[i]] 53 | if b != z: 54 | z = '1' 55 | else: 56 | z = '0' 57 | base = base[:i] + z + base[i + 1:] 58 | i += 1 59 | 60 | for i in range(0, 6): 61 | apv += hex(int(base[i * 8:i * 8 + 8], 2))[2:].zfill(2).upper() + ' ' 62 | 63 | return apv 64 | 65 | 66 | def a8_2(isk_c): 67 | '''MC9S12DG256 (algo2)(Megane 2, Scenic 2)''' 68 | apv = '' 69 | isk = isk_c.replace(' ', '').decode('hex') 70 | if len(isk) != 6: 71 | return None 72 | bit_i = '' 73 | for c in isk: 74 | bit_i += bin(ord(c))[2:].zfill(8) 75 | 76 | base = '' 77 | for b in a8_xor_2: 78 | base = base + bin(b)[2:].zfill(8) 79 | 80 | i = 0 81 | for b in base: 82 | z = bit_i[a8_mess[i]] 83 | if b != z: 84 | z = '1' 85 | else: 86 | z = '0' 87 | base = base[:i] + z + base[i + 1:] 88 | i += 1 89 | 90 | for i in range(0, 6): 91 | apv += hex(int(base[i * 8:i * 8 + 8], 2))[2:].zfill(2).upper() + ' ' 92 | 93 | return apv 94 | 95 | 96 | def get_isk(ecu_response): 97 | ecu_response = ecu_response.replace(' ', '').strip() 98 | return ecu_response[19 * 2:25 * 2] 99 | 100 | 101 | class CardProg(gui.QDialog): 102 | def __init__(self): 103 | super(CardProg, self).__init__() 104 | options.debug = True 105 | self.apvok = False 106 | self.megane_ecu = ecu.Ecu_file(ecufile, True) 107 | self.start_session_request = self.megane_ecu.requests[u'Start Diagnostic Session'] 108 | self.after_sale_request = self.megane_ecu.requests[u'ACCEDER AU MODE APRES-VENTE'] 109 | self.learn_key_request = self.megane_ecu.requests[u'APPRENDRE BADGE'] 110 | self.key_bits_status = self.megane_ecu.requests[u'Status général des opérations badges Bits'] 111 | self.key_bytes_status = self.megane_ecu.requests[u'Status général des opérations badges Octets'] 112 | self.reserved_frame_request = self.megane_ecu.requests[u'Trame AB: Trame réservée'] 113 | self.learn_validate_request = self.megane_ecu.requests[u'SORTIE DU MODE APV : VALIDATION'] 114 | self.learn_cancel_request = self.megane_ecu.requests[u'SORTIE DU MODE APV : ABANDON'] 115 | 116 | self.ecu_connect() 117 | self.start_diag_session() 118 | 119 | self.apv_access_button = gui.QPushButton(_("ENTER AFTER SALE MODE")) 120 | self.apv_access_button.clicked.connect(self.set_apv_from_input) 121 | self.pininput = gui.QLineEdit() 122 | self.pininput.setText("0" * 12) 123 | self.pininput.setInputMask("H" * 12) 124 | self.iskoutput = gui.QLineEdit() 125 | self.iskoutput.setInputMask("H" * 12) 126 | self.numkeys_label = gui.QLabel("0") 127 | self.currentcardide = gui.QLineEdit() 128 | self.currentcardide.setReadOnly(True) 129 | self.apv_status = gui.QLabel("") 130 | self.apv_status.setAlignment(core.Qt.AlignHCenter) 131 | label = gui.QLabel(_("MEGANE II CARD PROGRAMMING
EXPERIMENTAL : NOT TESTED YET
")) 132 | label.setAlignment(core.Qt.AlignHCenter) 133 | self.learnbutton = gui.QPushButton(_("LEARN")) 134 | self.validatebutton = gui.QPushButton(_("VALIDATE")) 135 | self.cancelbutton = gui.QPushButton(_("CANCEL")) 136 | 137 | self.algocheck = gui.QCheckBox(_("Algo 2")) 138 | self.algocheck.setChecked(False) 139 | 140 | self.learnbutton.clicked.connect(self.learn_action) 141 | self.validatebutton.clicked.connect(self.validate_action) 142 | self.cancelbutton.clicked.connect(self.cancel_action) 143 | self.iskoutput.textChanged.connect(self.calculate_pin) 144 | self.algocheck.toggled.connect(self.calculate_pin) 145 | 146 | layout = gui.QGridLayout() 147 | layout.addWidget(label, 0, 0, 1, 0) 148 | layout.addWidget(gui.QLabel(_("ISK")), 1, 0) 149 | layout.addWidget(self.iskoutput, 1, 1) 150 | layout.addWidget(gui.QLabel(_("PIN")), 2, 0) 151 | layout.addWidget(self.pininput, 2, 1) 152 | layout.addWidget(self.algocheck, 3, 1) 153 | layout.addWidget(self.apv_access_button, 4, 0, 1, 0) 154 | layout.addWidget(self.apv_status, 5, 0, 1, 0) 155 | layout.addWidget(gui.QLabel(_("Num key learnt")), 6, 0) 156 | layout.addWidget(self.numkeys_label, 6, 1) 157 | layout.addWidget(gui.QLabel(_("CARD IDE")), 7, 0) 158 | layout.addWidget(self.currentcardide, 7, 1) 159 | layout.addWidget(self.learnbutton, 8, 0, 1, 0) 160 | layout.addWidget(self.validatebutton, 9, 0) 161 | layout.addWidget(self.cancelbutton, 9, 1) 162 | 163 | self.setLayout(layout) 164 | 165 | # I have to use a timer here to avoid ECU from escaping session mode 166 | # A shot every 1.5 seconds is enough, normally 167 | self.tester_timer = core.QTimer() 168 | self.tester_timer.setSingleShot(False) 169 | self.tester_timer.setInterval(1500) 170 | self.tester_timer.timeout.connect(self.check_all) 171 | 172 | isk = self.get_isk() 173 | self.iskoutput.setText(isk) 174 | 175 | self.tester_timer.start() 176 | 177 | def calculate_pin(self): 178 | ISK = ''.join(str(ord(c)) for c in str(self.iskoutput.text())) 179 | if len(ISK) == 12: 180 | if self.algocheck.checkState(): 181 | PIN = a8_2(ISK) 182 | else: 183 | PIN = a8(ISK) 184 | if PIN is not None: 185 | self.pininput.setText(PIN) 186 | self.iskoutput.setStyleSheet("color: green;") 187 | return 188 | 189 | self.pininput.setText("000000000000") 190 | self.iskoutput.setStyleSheet("color: red;") 191 | 192 | def learn_action(self): 193 | self.learn_key_request.send_request() 194 | 195 | def validate_action(self): 196 | self.learn_validate_request.send_request() 197 | 198 | def cancel_action(self): 199 | self.learn_cancel_request.send_request() 200 | 201 | def get_isk(self): 202 | # No dataitem for ISK :( 203 | # Need to decode by myself 204 | if options.simulation_mode: 205 | reply = "61 AB 02 FC 0D 08 51 4C 86 55 54 00 00 00 00 00 00 00 00 8D E8 EE 16 79 D3 C9 A7 A7 CC " \ 206 | "F6 AC 00 00 00 00 00 00 2A" 207 | else: 208 | reply = options.elm.request(self.reserved_frame_request.sentbytes) 209 | 210 | if reply.startswith('7F') or reply.startswith('WRONG'): 211 | options.main_window.logview.append(_("Cannot get ISK, check connections and UCH compatibility")) 212 | return 213 | 214 | isk = reply.replace(' ', '').strip() 215 | return get_isk(isk) 216 | 217 | def ecu_connect(self): 218 | connection = self.megane_ecu.connect_to_hardware() 219 | if not connection: 220 | options.main_window.logview.append(_("Cannot connect to ECU")) 221 | self.finished() 222 | 223 | def check_all(self): 224 | self.check_apv_status() 225 | self.check_num_key_learnt() 226 | 227 | def set_apv_from_input(self): 228 | apv = ''.join(str(ord(c)) for c in str(self.pininput.text())) 229 | if len(apv) != 12: 230 | return 231 | self.after_sale_request.send_request({u'Code APV': apv}) 232 | 233 | def enable_buttons(self, enable): 234 | self.learnbutton.setEnabled(enable) 235 | self.validatebutton.setEnabled(enable) 236 | self.cancelbutton.setEnabled(enable) 237 | 238 | def check_apv_status(self): 239 | key_bits_status_values = self.key_bits_status.send_request({}, "61 06 21 21 20 00 00 00 08 00 00 80 03") 240 | 241 | value_apv_ok = key_bits_status_values[u'VSC Code APV_Reconnu'] 242 | value_apv_reaff = key_bits_status_values[u'VSC ModeAPV_ReaffArmé'] 243 | value_apv_uch_reaff = key_bits_status_values[u'VSC ModeAPV_AppUCH_Armé'] 244 | 245 | if value_apv_ok == '0': 246 | self.apv_status.setText(_("PIN CODE NOT RECOGNIZED")) 247 | self.apvok = False 248 | self.enable_buttons(False) 249 | return 250 | 251 | if value_apv_reaff == '1': 252 | self.apv_status.setText(_("PIN CODE OK / KEY LEARNING")) 253 | self.enable_buttons(True) 254 | self.apvok = True 255 | return 256 | 257 | elif value_apv_uch_reaff == '1': 258 | self.apv_status.setText(_("PIN CODE OK / UCH LEARNING")) 259 | self.enable_buttons(True) 260 | self.apvok = True 261 | return 262 | 263 | self.apvok = False 264 | self.enable_buttons(False) 265 | 266 | self.apv_status.setText("UCH NOT READY") 267 | 268 | def check_num_key_learnt(self): 269 | key_bytes_status_value = self.key_bytes_status.send_request({}, "61 08 00 00 00 00 00 00 0A 00 00 00 00 00 00 " 270 | "00 00 00 00 00 00 00 00 00 00 02 00 00 01 2C " 271 | "00 00 01 2C 00 00 2C 00 00 01 2C") 272 | 273 | num_key_learnt = key_bytes_status_value[u'VSC NbTotalDeBadgeAppris'] 274 | current_key_ide = key_bytes_status_value[u'VSC Code_IDE'] 275 | 276 | self.numkeys_label.setText(num_key_learnt) 277 | self.currentcardide.setText(current_key_ide) 278 | 279 | def start_diag_session(self): 280 | sds_request = self.megane_ecu.requests[u"Start Diagnostic Session"] 281 | sds_stream = " ".join(sds_request.build_data_stream({})) 282 | if options.simulation_mode: 283 | print("SdS stream", sds_stream) 284 | return 285 | options.elm.start_session_can(sds_stream) 286 | 287 | 288 | def plugin_entry(): 289 | cp = CardProg() 290 | cp.exec_() 291 | -------------------------------------------------------------------------------- /clio3_eps_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | from binascii import unhexlify 6 | 7 | import PyQt5.QtCore as core 8 | import PyQt5.QtWidgets as gui 9 | import crcmod 10 | 11 | import ecu 12 | import options 13 | 14 | _ = options.translator('ddt4all') 15 | 16 | plugin_name = _("Modus/Clio III EPS Reset") 17 | category = _("EPS Tools") 18 | need_hw = True 19 | ecufile = "DAE_J77_X85_Gen2___v3.7" 20 | 21 | 22 | def calc_crc(vin=None): 23 | VIN = vin.encode("hex") 24 | VININT = unhexlify(VIN) 25 | 26 | crc16 = crcmod.predefined.Crc('x-25') 27 | crc16.update(VININT) 28 | crcle = crc16.hexdigest() 29 | # Seems that computed CRC is returned in little endian way 30 | # Convert it to big endian 31 | return crcle[2:4] + crcle[0:2] 32 | 33 | 34 | class Virginizer(gui.QDialog): 35 | def __init__(self): 36 | super(Virginizer, self).__init__() 37 | self.clio_eps = ecu.Ecu_file(ecufile, True) 38 | layout = gui.QVBoxLayout() 39 | infos = gui.QLabel( 40 | _("Modus/Clio III EPS VIRGINIZER
THIS PLUGIN WILL RESET EPS IMMO DATA
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 41 | infos.setAlignment(core.Qt.AlignHCenter) 42 | check_button = gui.QPushButton(_("BLANK STATUS & VIN READ")) 43 | self.status_check = gui.QLabel(_("Waiting")) 44 | self.status_check.setAlignment(core.Qt.AlignHCenter) 45 | self.virginize_button = gui.QPushButton(_("Virginize EPS")) 46 | 47 | self.setLayout(layout) 48 | self.virginize_button.setEnabled(False) 49 | self.virginize_button.clicked.connect(self.reset_ecu) 50 | check_button.clicked.connect(self.check_virgin_status) 51 | status_vin = gui.QLabel(_("VIN - READ")) 52 | status_vin.setAlignment(core.Qt.AlignHCenter) 53 | self.vin_input = gui.QLineEdit() 54 | self.vin_input.setReadOnly(True) 55 | 56 | status_vinout = gui.QLabel(_("VIN - WRITE")) 57 | status_vinout.setAlignment(core.Qt.AlignHCenter) 58 | self.vin_output = gui.QLineEdit() 59 | 60 | write_vin_button = gui.QPushButton(_("Write VIN")) 61 | write_vin_button.clicked.connect(self.write_vin) 62 | 63 | layout.addWidget(infos) 64 | layout.addWidget(check_button) 65 | layout.addWidget(self.status_check) 66 | layout.addWidget(self.virginize_button) 67 | layout.addWidget(self.virginize_button) 68 | 69 | layout.addWidget(status_vin) 70 | layout.addWidget(self.vin_input) 71 | layout.addWidget(status_vinout) 72 | layout.addWidget(self.vin_output) 73 | layout.addWidget(write_vin_button) 74 | 75 | self.ecu_connect() 76 | 77 | def read_vin(self): 78 | vin_read_request = self.clio_eps.requests[u'RDBLI - VIN'] 79 | vin_values = vin_read_request.send_request({}, "61 81 68 69 70 65 65 65 65 65 65 65 65 65 65 65 65 65 66 00 00") 80 | self.vin_input.setText(vin_values[u'VIN']) 81 | 82 | def write_vin(self): 83 | try: 84 | vin = str(self.vin_output.text().toAscii()).upper() 85 | self.vin_output.setText(vin) 86 | except: 87 | self.status_check.setText(_("VIN - INVALID")) 88 | return 89 | 90 | if len(vin) != 17: 91 | self.status_check.setText(_("VIN - BAD LENGTH")) 92 | return 93 | 94 | crc = calc_crc(vin).decode('hex') 95 | self.start_diag_session() 96 | vin_wrtie_request = self.clio_eps.requests[u'WDBLI - VIN'] 97 | write_response = vin_wrtie_request.send_request({u'VIN': vin, u'CRC VIN': crc}) 98 | if write_response is None: 99 | self.status_check.setText(_("VIN WRITE FAILED")) 100 | return 101 | 102 | self.status_check.setText(_("VIN WRITE OK")) 103 | 104 | def ecu_connect(self): 105 | connection = self.clio_eps.connect_to_hardware() 106 | if not connection: 107 | options.main_window.logview.append(_("Cannot connect to ECU")) 108 | self.finished() 109 | 110 | def check_virgin_status(self): 111 | self.start_diag_session() 112 | self.read_vin() 113 | virigin_check_request = self.clio_eps.requests[u'RDBLI - System Frame'] 114 | virgin_check_values = virigin_check_request.send_request({}, "62 01 64 00 00 00 00 00 00 00 00 00 00 00 00 " \ 115 | "00 00 00 00 00 00 00 00 00") 116 | 117 | if virgin_check_values is not None: 118 | virgin_status = virgin_check_values[u"Dongle status"] 119 | 120 | if options.debug: 121 | print(virgin_status) 122 | 123 | if virgin_status == u'Système VIERGE - Aucun code mémorisé': 124 | self.virginize_button.setEnabled(False) 125 | self.status_check.setText(_("EPS virgin")) 126 | return 127 | else: 128 | self.virginize_button.setEnabled(True) 129 | self.status_check.setText(_("EPS coded")) 130 | return 131 | 132 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 133 | 134 | def start_diag_session_fb(self): 135 | sds_request = self.clio_eps.requests[u"SDS - Start Diagnostic $FB"] 136 | sds_stream = " ".join(sds_request.build_data_stream({})) 137 | 138 | if options.simulation_mode: 139 | print("SdSFB stream", sds_stream) 140 | return 141 | 142 | options.elm.start_session_can(sds_stream) 143 | 144 | def start_diag_session(self): 145 | sds_request = self.clio_eps.requests[u"Start Diagnostic Session"] 146 | sds_stream = " ".join(sds_request.build_data_stream({})) 147 | 148 | if options.simulation_mode: 149 | print("SdSC0 stream", sds_stream) 150 | return 151 | 152 | options.elm.start_session_can(sds_stream) 153 | 154 | def reset_ecu(self): 155 | self.start_diag_session_fb() 156 | reset_request = self.clio_eps.requests[u"WDBLI - Erase of Dongle_ID code"] 157 | request_response = reset_request.send_request() 158 | 159 | if request_response is not None: 160 | self.status_check.setText(_("CLEAR EXECUTED")) 161 | else: 162 | self.status_check.setText(_("CLEAR FAILED")) 163 | 164 | 165 | def plugin_entry(): 166 | v = Virginizer() 167 | v.exec_() 168 | -------------------------------------------------------------------------------- /clio4_eps_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | import PyQt5.QtCore as core 6 | import PyQt5.QtWidgets as gui 7 | 8 | import ecu 9 | import options 10 | 11 | _ = options.translator('ddt4all') 12 | 13 | plugin_name = _("Clio IV EPS Reset") 14 | category = _("EPS Tools") 15 | need_hw = True 16 | ecufile = "X98ph2_X87ph2_EPS_HFP_v1.00_20150622T140219_20160726T172209" 17 | 18 | 19 | class Virginizer(gui.QDialog): 20 | def __init__(self): 21 | super(Virginizer, self).__init__() 22 | self.clio_eps = ecu.Ecu_file(ecufile, True) 23 | layout = gui.QVBoxLayout() 24 | infos = gui.QLabel( 25 | _("Clio IV EPS VIRGINIZER
THIS PLUGIN WILL RESET EPS IMMO DATA
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 26 | infos.setAlignment(core.Qt.AlignHCenter) 27 | check_button = gui.QPushButton(_("Check EPS Virgin")) 28 | self.status_check = gui.QLabel(_("Waiting")) 29 | self.status_check.setAlignment(core.Qt.AlignHCenter) 30 | self.virginize_button = gui.QPushButton(_("Virginize EPS")) 31 | layout.addWidget(infos) 32 | layout.addWidget(check_button) 33 | layout.addWidget(self.status_check) 34 | layout.addWidget(self.virginize_button) 35 | self.setLayout(layout) 36 | self.virginize_button.setEnabled(False) 37 | self.virginize_button.clicked.connect(self.reset_ecu) 38 | check_button.clicked.connect(self.check_virgin_status) 39 | self.ecu_connect() 40 | 41 | def ecu_connect(self): 42 | connection = self.clio_eps.connect_to_hardware() 43 | if not connection: 44 | options.main_window.logview.append(_("Cannot connect to ECU")) 45 | self.finished() 46 | 47 | def check_virgin_status(self): 48 | self.start_diag_session_c0() 49 | 50 | virigin_check_request = self.clio_eps.requests[u'DataRead.DongleState'] 51 | request_values = virigin_check_request.send_request() 52 | 53 | if request_values is not None: 54 | if u'DongleState' in request_values: 55 | donglestate = request_values[u'DongleState'] 56 | 57 | if donglestate == u'NotOperational': 58 | self.virginize_button.setEnabled(False) 59 | self.status_check.setText(_("EPS not operational")) 60 | return 61 | 62 | if donglestate == u'OperationalBlanked': 63 | self.virginize_button.setEnabled(False) 64 | self.status_check.setText(_("EPS virgin")) 65 | return 66 | 67 | if donglestate == u'OperationalLearnt': 68 | self.virginize_button.setEnabled(True) 69 | self.status_check.setText(_("EPS coded")) 70 | return 71 | 72 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 73 | 74 | def start_diag_session_fa(self): 75 | sds_request = self.clio_eps.requests[u"StartDiagnosticSession.supplierSession"] 76 | sds_stream = " ".join(sds_request.build_data_stream({})) 77 | if options.simulation_mode: 78 | print("SdSFA stream", sds_stream) 79 | return 80 | options.elm.start_session_can(sds_stream) 81 | 82 | def start_diag_session_c0(self): 83 | sds_request = self.clio_eps.requests[u"StartDiagnosticSession.extendedSession"] 84 | sds_stream = " ".join(sds_request.build_data_stream({})) 85 | if options.simulation_mode: 86 | print("SdSC0 stream", sds_stream) 87 | return 88 | options.elm.start_session_can(sds_stream) 89 | 90 | def reset_ecu(self): 91 | self.start_diag_session_fa() 92 | 93 | reset_request = self.clio_eps.requests[u"SRBLID.DongleBlanking.Request"] 94 | request_response = reset_request.send_request({u'Dongle.Code': '1976'}) 95 | 96 | if request_response is not None: 97 | self.status_check.setText(_("CLEAR EXECUTED")) 98 | else: 99 | self.status_check.setText(_("CLEAR FAILED")) 100 | 101 | 102 | def plugin_entry(): 103 | v = Virginizer() 104 | v.exec_() 105 | -------------------------------------------------------------------------------- /laguna2_uch_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | # This is an example plugin 5 | 6 | import PyQt5.QtCore as core 7 | import PyQt5.QtWidgets as gui 8 | 9 | import ecu 10 | import options 11 | 12 | _ = options.translator('ddt4all') 13 | 14 | plugin_name = _("Laguna II UCH Reset") 15 | category = _("UCH Tools") 16 | need_hw = True 17 | ecufile = "UCH___M2S_X74_et_X73" 18 | 19 | 20 | class Virginizer(gui.QDialog): 21 | def __init__(self): 22 | super(Virginizer, self).__init__() 23 | self.laguna_uch = ecu.Ecu_file(ecufile, True) 24 | layout = gui.QVBoxLayout() 25 | infos = gui.QLabel( 26 | _("LAGUNA II UCH VIRGINIZER
THIS PLUGIN WILL ERASE YOUR UCH
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 27 | infos.setAlignment(core.Qt.AlignHCenter) 28 | check_button = gui.QPushButton(_("Check UCH Virgin")) 29 | self.status_check = gui.QLabel(_("Waiting")) 30 | self.status_check.setAlignment(core.Qt.AlignHCenter) 31 | self.virginize_button = gui.QPushButton(_("Virginize UCH")) 32 | layout.addWidget(infos) 33 | layout.addWidget(check_button) 34 | layout.addWidget(self.status_check) 35 | layout.addWidget(self.virginize_button) 36 | self.setLayout(layout) 37 | self.virginize_button.setEnabled(False) 38 | self.virginize_button.clicked.connect(self.reset_ecu) 39 | check_button.clicked.connect(self.check_virgin_status) 40 | self.ecu_connect() 41 | # Start comm immediately 42 | self.start_diag_session_study() 43 | 44 | def ecu_connect(self): 45 | connection = self.laguna_uch.connect_to_hardware() 46 | if not connection: 47 | options.main_window.logview.append(_("Cannot connect to ECU")) 48 | self.finished() 49 | 50 | def check_virgin_status(self): 51 | self.start_diag_session_aftersales() 52 | 53 | virigin_check_request = self.laguna_uch.requests[u'Lecture Etats Antidémarrage et acces'] 54 | response_values = virigin_check_request.send_request() 55 | 56 | if response_values is not None: 57 | virgin = response_values[u"UCH vierge"] 58 | 59 | if virgin == u'oui': 60 | self.virginize_button.setEnabled(False) 61 | self.status_check.setText(_("UCH virgin")) 62 | return 63 | 64 | if virgin == u'non': 65 | self.virginize_button.setEnabled(True) 66 | self.status_check.setText(_("UCH coded")) 67 | return 68 | 69 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 70 | 71 | def start_diag_session_study(self): 72 | sds_request = self.laguna_uch.requests[u"Start Diagnostic Session"] 73 | sds_stream = " ".join(sds_request.build_data_stream({u'Session Name': u'Etude'})) 74 | if options.simulation_mode: 75 | print("SdSA stream", sds_stream) 76 | return 77 | options.elm.start_session_iso(sds_stream) 78 | 79 | def start_diag_session_aftersales(self): 80 | sds_request = self.laguna_uch.requests[u"Start Diagnostic Session"] 81 | sds_stream = " ".join(sds_request.build_data_stream({u'Session Name': u'APV'})) 82 | if options.simulation_mode: 83 | print("SdSS stream", sds_stream) 84 | return 85 | options.elm.request(sds_stream) 86 | 87 | def reset_ecu(self): 88 | self.start_diag_session_study() 89 | 90 | reset_request = self.laguna_uch.requests[u"Effacement_données_antidem_acces"] 91 | request_response = reset_request.send_request() 92 | 93 | if request_response is not None: 94 | self.status_check.setText(_("CLEAR EXECUTED")) 95 | else: 96 | self.status_check.setText(_("CLEAR FAILED")) 97 | 98 | 99 | def plugin_entry(): 100 | v = Virginizer() 101 | v.exec_() 102 | -------------------------------------------------------------------------------- /laguna3_uch_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | import PyQt5.QtCore as core 6 | import PyQt5.QtWidgets as gui 7 | 8 | import ecu 9 | import options 10 | 11 | _ = options.translator('ddt4all') 12 | 13 | plugin_name = _("Laguna III UCH Reset") 14 | category = _("UCH Tools") 15 | need_hw = True 16 | ecufile = "BCM_X91_L43_S_S_SWC_v1.30_20140613T140906" 17 | 18 | 19 | class Virginizer(gui.QDialog): 20 | def __init__(self): 21 | super(Virginizer, self).__init__() 22 | self.megane_uch = ecu.Ecu_file(ecufile, True) 23 | layout = gui.QVBoxLayout() 24 | infos = gui.QLabel( 25 | _("LAGUNA III UCH VIRGINIZER
THIS PLUGIN WILL ERASE YOUR UCH
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 26 | infos.setAlignment(core.Qt.AlignHCenter) 27 | check_button = gui.QPushButton(_("Check UCH Virgin")) 28 | self.status_check = gui.QLabel(_("Waiting")) 29 | self.status_check.setAlignment(core.Qt.AlignHCenter) 30 | self.virginize_button = gui.QPushButton(_("Virginize UCH")) 31 | layout.addWidget(infos) 32 | layout.addWidget(check_button) 33 | layout.addWidget(self.status_check) 34 | layout.addWidget(self.virginize_button) 35 | self.setLayout(layout) 36 | self.virginize_button.setEnabled(False) 37 | self.virginize_button.clicked.connect(self.reset_ecu) 38 | check_button.clicked.connect(self.check_virgin_status) 39 | self.ecu_connect() 40 | 41 | def ecu_connect(self): 42 | connection = self.megane_uch.connect_to_hardware() 43 | if not connection: 44 | options.main_window.logview.append(_("Cannot connect to ECU")) 45 | self.finished() 46 | 47 | def check_virgin_status(self): 48 | self.start_diag_session_aftersales() 49 | 50 | virigin_check_request = self.megane_uch.requests[ 51 | u'Read_A_AC_General_Identifiers_Learning_Status_(bits)_BCM_Input/Output'] 52 | virgin_check_values = virigin_check_request.send_request() 53 | 54 | if virgin_check_values is not None: 55 | virgin = virgin_check_values[u"BCM_IS_BLANK_S"] 56 | if virgin == u'true': 57 | self.virginize_button.setEnabled(False) 58 | self.status_check.setText(_("UCH virgin")) 59 | return 60 | 61 | if virgin == u'false': 62 | self.virginize_button.setEnabled(True) 63 | self.status_check.setText(_("UCH coded")) 64 | return 65 | 66 | self.status_check.setText("UNEXPECTED RESPONSE") 67 | 68 | def start_diag_session_aftersales(self): 69 | sds_request = self.megane_uch.requests[u"Start Diagnostic Session"] 70 | sds_stream = " ".join(sds_request.build_data_stream({})) 71 | if options.simulation_mode: 72 | print("SdSS stream", sds_stream) 73 | return 74 | options.elm.start_session_can(sds_stream) 75 | 76 | def reset_ecu(self): 77 | self.start_diag_session_aftersales() 78 | 79 | reset_request = self.megane_uch.requests[u"SR_RESERVED VSC 1"] 80 | request_response = reset_request.send_request() 81 | 82 | if request_response is not None: 83 | self.status_check.setText(_("CLEAR EXECUTED")) 84 | else: 85 | self.status_check.setText(_("CLEAR FAILED")) 86 | 87 | 88 | def plugin_entry(): 89 | v = Virginizer() 90 | v.exec_() 91 | -------------------------------------------------------------------------------- /megane2_uch_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | # This is an example plugin 5 | 6 | import PyQt5.QtCore as core 7 | import PyQt5.QtWidgets as gui 8 | 9 | import ecu 10 | import options 11 | 12 | _ = options.translator('ddt4all') 13 | 14 | plugin_name = _("Megane/Scenic II UCH Reset") 15 | category = _("UCH Tools") 16 | need_hw = True 17 | 18 | 19 | class Virginizer(gui.QDialog): 20 | def __init__(self): 21 | super(Virginizer, self).__init__() 22 | self.megane_uch = ecu.Ecu_file("UCH_84_J84_03_60", True) 23 | layout = gui.QVBoxLayout() 24 | infos = gui.QLabel( 25 | _("MEGANE II UCH VIRGINIZER
THIS PLUGIN WILL ERASE YOUR UCH
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 26 | infos.setAlignment(core.Qt.AlignHCenter) 27 | check_button = gui.QPushButton(_("Check UCH Virgin")) 28 | self.status_check = gui.QLabel(_("Waiting")) 29 | self.status_check.setAlignment(core.Qt.AlignHCenter) 30 | self.virginize_button = gui.QPushButton(_("Virginize UCH")) 31 | layout.addWidget(infos) 32 | layout.addWidget(check_button) 33 | layout.addWidget(self.status_check) 34 | layout.addWidget(self.virginize_button) 35 | self.setLayout(layout) 36 | self.virginize_button.setEnabled(False) 37 | self.virginize_button.clicked.connect(self.reset_ecu) 38 | check_button.clicked.connect(self.check_virgin_status) 39 | self.ecu_connect() 40 | 41 | def ecu_connect(self): 42 | connection = self.megane_uch.connect_to_hardware() 43 | if not connection: 44 | options.main_window.logview.append(_("Cannot connect to ECU")) 45 | self.finished() 46 | 47 | def check_virgin_status(self): 48 | self.start_diag_session_aftersales() 49 | 50 | virigin_check_request = self.megane_uch.requests[u'Status général des opérations badges Bits'] 51 | request_values = virigin_check_request.send_request() 52 | 53 | if request_values is not None: 54 | virgin = request_values[u"VSC UCH vierge (NbBadgeAppris=0)"] 55 | if virgin == u'Vierge': 56 | self.virginize_button.setEnabled(False) 57 | self.status_check.setText(_("UCH virgin")) 58 | return 59 | 60 | if virgin == u'Codée': 61 | self.virginize_button.setEnabled(True) 62 | self.status_check.setText(_("UCH coded")) 63 | return 64 | 65 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 66 | 67 | def start_diag_session_study(self): 68 | sds_request = self.megane_uch.requests[u"StartDiagSession Etude"] 69 | sds_stream = " ".join(sds_request.build_data_stream({})) 70 | if options.simulation_mode: 71 | print("SdSA stream", sds_stream) 72 | return 73 | options.elm.start_session_can(sds_stream) 74 | 75 | def start_diag_session_aftersales(self): 76 | sds_request = self.megane_uch.requests[u"Start Diagnostic Session"] 77 | sds_stream = " ".join(sds_request.build_data_stream({})) 78 | if options.simulation_mode: 79 | print("SdSS stream", sds_stream) 80 | return 81 | options.elm.start_session_can(sds_stream) 82 | 83 | def reset_ecu(self): 84 | self.start_diag_session_study() 85 | 86 | reset_request = self.megane_uch.requests[u"RAZ EEPROM"] 87 | request_response = reset_request.send_request() 88 | 89 | if request_response is not None: 90 | self.status_check.setText(_("CLEAR EXECUTED")) 91 | else: 92 | self.status_check.setText(_("CLEAR FAILED")) 93 | 94 | 95 | def plugin_entry(): 96 | v = Virginizer() 97 | v.exec_() 98 | -------------------------------------------------------------------------------- /megane3_ab_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | import PyQt5.QtCore as core 6 | import PyQt5.QtWidgets as gui 7 | 8 | import ecu 9 | import options 10 | 11 | _ = options.translator('ddt4all') 12 | 13 | plugin_name = _("Megane3 AIRBAG Reset") 14 | category = _("Airbag Tools") 15 | need_hw = True 16 | ecufile = "MRSZ_X95_L38_L43_L47_20110505T101858" 17 | 18 | 19 | class Virginizer(gui.QDialog): 20 | def __init__(self): 21 | super(Virginizer, self).__init__() 22 | self.airbag_ecu = ecu.Ecu_file(ecufile, True) 23 | layout = gui.QVBoxLayout() 24 | infos = gui.QLabel(_("Megane III
" 25 | "AIRBAG VIRGINIZER
THIS PLUGIN WILL UNLOCK AIRBAG CRASH DATA
" 26 | "GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 27 | infos.setAlignment(core.Qt.AlignHCenter) 28 | check_button = gui.QPushButton(_("Check ACU Virgin")) 29 | self.status_check = gui.QLabel(_("Waiting")) 30 | self.status_check.setAlignment(core.Qt.AlignHCenter) 31 | self.virginize_button = gui.QPushButton(_("Virginize ACU")) 32 | layout.addWidget(infos) 33 | layout.addWidget(check_button) 34 | layout.addWidget(self.status_check) 35 | layout.addWidget(self.virginize_button) 36 | self.setLayout(layout) 37 | self.virginize_button.setEnabled(True) 38 | self.virginize_button.clicked.connect(self.reset_ecu) 39 | check_button.clicked.connect(self.check_virgin_status) 40 | self.ecu_connect() 41 | 42 | def ecu_connect(self): 43 | connection = self.airbag_ecu.connect_to_hardware() 44 | if not connection: 45 | options.main_window.logview.append(_("Cannot connect to ECU")) 46 | self.finished() 47 | 48 | def check_virgin_status(self): 49 | self.start_diag_session() 50 | 51 | crash_reset_request = self.airbag_ecu.requests[u'Synthèse état UCE avant crash'] 52 | values_dict = crash_reset_request.send_request({}, "62 02 04 00 00 00 00 00 00 00 00 00 00 00 00") 53 | 54 | if values_dict is None: 55 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 56 | 57 | crash = values_dict[u'crash détecté'] 58 | 59 | if options.debug: 60 | print(">> ", crash) 61 | 62 | if crash == u'crash détecté': 63 | self.status_check.setText(_("CRASH DETECTED")) 64 | else: 65 | self.status_check.setText(-("NO CRASH DETECTED")) 66 | 67 | def start_diag_session_fa(self): 68 | sds_request = self.airbag_ecu.requests[u"Start Diagnostic Session"] 69 | 70 | sds_stream = " ".join(sds_request.build_data_stream({u"Session Name": u"systemSupplierSpecific"})) 71 | if options.simulation_mode: 72 | print("SdSFA stream", sds_stream) 73 | return 74 | options.elm.start_session_can(sds_stream) 75 | 76 | def start_diag_session(self): 77 | sds_request = self.airbag_ecu.requests[u"Start Diagnostic Session"] 78 | 79 | sds_stream = " ".join(sds_request.build_data_stream({u"Session Name": u"extendedDiagnosticSession"})) 80 | if options.simulation_mode: 81 | print("SdS stream", sds_stream) 82 | return 83 | options.elm.start_session_can(sds_stream) 84 | 85 | def reset_ecu(self): 86 | self.start_diag_session_fa() 87 | 88 | reset_request = self.airbag_ecu.requests[u"Reset crash ou accès au mode fournisseur"] 89 | request_response = reset_request.send_request({u"code d'accès pour reset UCE": '27081977'}) 90 | 91 | if request_response is not None: 92 | self.status_check.setText(_("CLEAR EXECUTED")) 93 | else: 94 | self.status_check.setText(_("CLEAR FAILED")) 95 | 96 | 97 | def plugin_entry(): 98 | v = Virginizer() 99 | v.exec_() 100 | -------------------------------------------------------------------------------- /megane3_eps_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | import PyQt5.QtCore as core 6 | import PyQt5.QtWidgets as gui 7 | 8 | import ecu 9 | import options 10 | 11 | _ = options.translator('ddt4all') 12 | 13 | plugin_name = _("ZOE/FLENCE/Megane III/Scenic III EPS Reset") 14 | category = _("EPS Tools") 15 | need_hw = True 16 | 17 | 18 | class Virginizer(gui.QDialog): 19 | def __init__(self): 20 | super(Virginizer, self).__init__() 21 | self.megane_eps = ecu.Ecu_file("DAE_X95_X38_X10_v1.88_20120228T113904", True) 22 | layout = gui.QVBoxLayout() 23 | infos = gui.QLabel( 24 | _("ZOE/FLENCE/Megane III/Scenic III EPS VIRGINIZER
THIS PLUGIN WILL RESET EPS IMMO DATA
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 25 | infos.setAlignment(core.Qt.AlignHCenter) 26 | check_button = gui.QPushButton(_("Check EPS Virgin")) 27 | self.status_check = gui.QLabel(_("Waiting")) 28 | self.status_check.setAlignment(core.Qt.AlignHCenter) 29 | self.virginize_button = gui.QPushButton(_("Virginize EPS")) 30 | layout.addWidget(infos) 31 | layout.addWidget(check_button) 32 | layout.addWidget(self.status_check) 33 | layout.addWidget(self.virginize_button) 34 | self.setLayout(layout) 35 | self.virginize_button.setEnabled(False) 36 | self.virginize_button.clicked.connect(self.reset_ecu) 37 | check_button.clicked.connect(self.check_virgin_status) 38 | self.ecu_connect() 39 | 40 | def ecu_connect(self): 41 | connection = self.megane_eps.connect_to_hardware() 42 | if not connection: 43 | options.main_window.logview.append(_("Cannot connect to ECU")) 44 | self.finished() 45 | 46 | def check_virgin_status(self): 47 | self.start_diag_session_c0() 48 | 49 | virigin_check_request = self.megane_eps.requests[u'DataRead.DID - Dongle state'] 50 | request_response = virigin_check_request.send_request({}, "62 01 64 00 00 00 00 00 00 00 00 00 00 00 00") 51 | 52 | if request_response is not None: 53 | if u'DID - Dongle state' in request_response: 54 | donglestate = request_response[u'DID - Dongle state'] 55 | if donglestate == u'Not operational': 56 | self.virginize_button.setEnabled(False) 57 | self.status_check.setText(_("EPS not operational")) 58 | return 59 | 60 | if donglestate == u'Operational blank': 61 | self.virginize_button.setEnabled(False) 62 | self.status_check.setText(_("EPS virgin")) 63 | return 64 | 65 | if donglestate == u'Operational learnt': 66 | self.virginize_button.setEnabled(True) 67 | self.status_check.setText(_("EPS coded")) 68 | return 69 | 70 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 71 | 72 | def start_diag_session_fa(self): 73 | sds_request = self.megane_eps.requests[u"SDS - Start Diagnostic Session $FA"] 74 | sds_stream = " ".join(sds_request.build_data_stream({})) 75 | if options.simulation_mode: 76 | print("SdSFA stream", sds_stream) 77 | return 78 | options.elm.start_session_can(sds_stream) 79 | 80 | def start_diag_session_c0(self): 81 | sds_request = self.megane_eps.requests[u"SDS - Start Diagnostic Session $C0"] 82 | sds_stream = " ".join(sds_request.build_data_stream({})) 83 | if options.simulation_mode: 84 | print("SdSC0 stream", sds_stream) 85 | return 86 | options.elm.start_session_can(sds_stream) 87 | 88 | def reset_ecu(self): 89 | self.start_diag_session_fa() 90 | 91 | reset_request = self.megane_eps.requests[u"SRBLID - Dongle blanking"] 92 | request_response = reset_request.send_request() 93 | 94 | if request_response is not None: 95 | self.status_check.setText(_("CLEAR EXECUTED")) 96 | else: 97 | self.status_check.setText(_("CLEAR FAILED")) 98 | 99 | 100 | def plugin_entry(): 101 | v = Virginizer() 102 | v.exec_() 103 | -------------------------------------------------------------------------------- /megane3_uch_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | 6 | import PyQt5.QtCore as core 7 | import PyQt5.QtWidgets as gui 8 | 9 | import ecu 10 | import options 11 | 12 | _ = options.translator('ddt4all') 13 | 14 | plugin_name = _("Megane/Scenic III UCH Reset") 15 | category = _("UCH Tools") 16 | need_hw = True 17 | ecufile = "BCM_X95_SW_2_V_1_2" 18 | 19 | 20 | class Virginizer(gui.QDialog): 21 | def __init__(self): 22 | super(Virginizer, self).__init__() 23 | self.megane_uch = ecu.Ecu_file(ecufile, True) 24 | layout = gui.QVBoxLayout() 25 | infos = gui.QLabel( 26 | _("MEGANE III UCH VIRGINIZER
THIS PLUGIN WILL ERASE YOUR UCH
GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 27 | infos.setAlignment(core.Qt.AlignHCenter) 28 | check_button = gui.QPushButton(_("Check UCH Virgin")) 29 | self.status_check = gui.QLabel(_("Waiting")) 30 | self.status_check.setAlignment(core.Qt.AlignHCenter) 31 | self.virginize_button = gui.QPushButton(_("Virginize UCH")) 32 | layout.addWidget(infos) 33 | layout.addWidget(check_button) 34 | layout.addWidget(self.status_check) 35 | layout.addWidget(self.virginize_button) 36 | self.setLayout(layout) 37 | self.virginize_button.setEnabled(False) 38 | self.virginize_button.clicked.connect(self.reset_ecu) 39 | check_button.clicked.connect(self.check_virgin_status) 40 | self.ecu_connect() 41 | 42 | def ecu_connect(self): 43 | connection = self.megane_uch.connect_to_hardware() 44 | if not connection: 45 | options.main_window.logview.append(_("Cannot connect to ECU")) 46 | self.finished() 47 | 48 | def check_virgin_status(self): 49 | self.start_diag_session_aftersales() 50 | 51 | virigin_check_request = self.megane_uch.requests[ 52 | u'Read_A_AC_General_Identifiers_Learning_Status_(bits)_BCM_Input/Output'] 53 | virgin_check_request_values = virigin_check_request.send_request() 54 | 55 | if virgin_check_request_values is not None: 56 | virgin_value = virgin_check_request_values[u"VSC UCH vierge (NbBadgeAppris=0)"] 57 | 58 | if virgin_value == u'Actif': 59 | self.virginize_button.setEnabled(False) 60 | self.status_check.setText(_("UCH virgin")) 61 | return 62 | 63 | if virgin_value == u'inactif': 64 | self.virginize_button.setEnabled(True) 65 | self.status_check.setText(_("UCH coded")) 66 | return 67 | 68 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 69 | 70 | def start_diag_session_aftersales(self): 71 | sds_request = self.megane_uch.requests[u"Start Diagnostic Session"] 72 | sds_stream = " ".join(sds_request.build_data_stream({})) 73 | if options.simulation_mode: 74 | print("SdSS stream", sds_stream) 75 | return 76 | options.elm.start_session_can(sds_stream) 77 | 78 | def reset_ecu(self): 79 | self.start_diag_session_aftersales() 80 | 81 | reset_request = self.megane_uch.requests[u"SR_RESERVED VSC 1"] 82 | request_response = reset_request.send_request() 83 | 84 | if request_response is not None: 85 | self.status_check.setText(_("CLEAR EXECUTED")) 86 | else: 87 | self.status_check.setText(_("CLEAR FAILED")) 88 | 89 | 90 | def plugin_entry(): 91 | v = Virginizer() 92 | v.exec_() 93 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | crcmod==1.7 -------------------------------------------------------------------------------- /rsat4_reset.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # (c) 2017 4 | 5 | 6 | import PyQt5.QtCore as core 7 | import PyQt5.QtWidgets as gui 8 | 9 | import ecu 10 | import options 11 | 12 | _ = options.translator('ddt4all') 13 | 14 | plugin_name = _("RSAT4 AIRBAG Reset") 15 | category = _("Airbag Tools") 16 | need_hw = True 17 | ecufile = "RSAT4_ACU_eng_v15_20150511T131328" 18 | 19 | 20 | class Virginizer(gui.QDialog): 21 | def __init__(self): 22 | super(Virginizer, self).__init__() 23 | self.airbag_ecu = ecu.Ecu_file(ecufile, True) 24 | layout = gui.QVBoxLayout() 25 | infos = gui.QLabel(_("TWINGO III/ZOE/DOKKER/DUSTER ph2/TRAFIC III/CAPTUR/LODGY ph1/2
" 26 | "AIRBAG VIRGINIZER
THIS PLUGIN WILL UNLOCK AIRBAG CRASH DATA
" 27 | "GO AWAY IF YOU HAVE NO IDEA OF WHAT IT MEANS
")) 28 | infos.setAlignment(core.Qt.AlignHCenter) 29 | check_button = gui.QPushButton(_("Check ACU Virgin")) 30 | self.status_check = gui.QLabel(_("Waiting")) 31 | self.status_check.setAlignment(core.Qt.AlignHCenter) 32 | self.virginize_button = gui.QPushButton(_("Virginize ACU")) 33 | layout.addWidget(infos) 34 | layout.addWidget(check_button) 35 | layout.addWidget(self.status_check) 36 | layout.addWidget(self.virginize_button) 37 | self.setLayout(layout) 38 | self.virginize_button.setEnabled(True) 39 | self.virginize_button.clicked.connect(self.reset_ecu) 40 | check_button.clicked.connect(self.check_virgin_status) 41 | self.ecu_connect() 42 | 43 | def ecu_connect(self): 44 | connection = self.airbag_ecu.connect_to_hardware() 45 | if not connection: 46 | options.main_window.logview.append(_("Cannot connect to ECU")) 47 | self.finished() 48 | 49 | def check_virgin_status(self): 50 | self.start_diag_session() 51 | 52 | crash_reset_request = self.airbag_ecu.requests[u'Reading of ECU state synthesis'] 53 | crash_response = crash_reset_request.send_request({}, "62 02 04 00 00 00 00 00 00 00 00 00 00 00 00") 54 | 55 | if crash_response is not None: 56 | if u"crash detected" in crash_response: 57 | crash = crash_response[u"crash detected"] 58 | 59 | if crash == u'crash detected': 60 | self.status_check.setText(_("CRASH DETECTED")) 61 | return 62 | if crash == u'no crash detected': 63 | self.status_check.setText(_("NO CRASH DETECTED")) 64 | return 65 | 66 | self.status_check.setText(_("UNEXPECTED RESPONSE")) 67 | 68 | def start_diag_session(self): 69 | sds_request = self.airbag_ecu.requests[u"Start Diagnostic Session"] 70 | 71 | sds_stream = " ".join(sds_request.build_data_stream({u'Session Name': u'extendedDiagnosticSession'})) 72 | if options.simulation_mode: 73 | print("SdSEX stream", sds_stream) 74 | return 75 | options.elm.start_session_can(sds_stream) 76 | 77 | def reset_ecu(self): 78 | self.start_diag_session() 79 | 80 | reset_request = self.airbag_ecu.requests[u"Reset Crash"] 81 | request_response = reset_request.send_request({u'CLEDEV For reset crash': '13041976'}) 82 | 83 | if request_response is not None: 84 | self.status_check.setText(_("CLEAR EXECUTED")) 85 | else: 86 | self.status_check.setText(_("CLEAR FAILED")) 87 | 88 | 89 | def plugin_entry(): 90 | v = Virginizer() 91 | v.exec_() 92 | -------------------------------------------------------------------------------- /vin_crc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Plugin to compute CRC from VIN 4 | # (c) 2017 5 | 6 | from binascii import hexlify 7 | from binascii import unhexlify 8 | 9 | import PyQt5.QtCore as core 10 | import PyQt5.QtWidgets as gui 11 | import crcmod.predefined 12 | 13 | import options 14 | 15 | _ = options.translator('ddt4all') 16 | 17 | plugin_name = _("CRC calculator") 18 | category = _("VIN") 19 | # We need an ELM to work 20 | need_hw = False 21 | 22 | 23 | def calc_crc(vin=None): 24 | VIN = hexlify(bytes(vin, 'utf-8')) 25 | VININT = unhexlify(VIN) 26 | 27 | crc16 = crcmod.predefined.mkCrcFun('x-25') 28 | crcle = hex(crc16(VININT))[2:].upper().zfill(4) 29 | print(crcle) 30 | # crcle = crc16.hexdigest() 31 | # Seems that computed CRC is returned in little endian way 32 | # Convert it to big endian 33 | return crcle[2:4] + crcle[0:2] 34 | 35 | 36 | class CrcWidget(gui.QDialog): 37 | def __init__(self): 38 | super(CrcWidget, self).__init__(None) 39 | layout = gui.QVBoxLayout() 40 | self.input = gui.QLineEdit() 41 | self.output = gui.QLineEdit() 42 | self.output.setStyleSheet("QLineEdit { color: rgb(255, 0, 0); }") 43 | info = gui.QLabel(_("CRC CALCULATOR")) 44 | info.setAlignment(core.Qt.AlignHCenter) 45 | self.output.setAlignment(core.Qt.AlignHCenter) 46 | layout.addWidget(info) 47 | layout.addWidget(self.input) 48 | layout.addWidget(self.output) 49 | self.input.textChanged.connect(self.recalc) 50 | self.setLayout(layout) 51 | self.output.setReadOnly(True) 52 | 53 | def recalc(self): 54 | vin = str(self.input.text()).upper() 55 | crc = calc_crc(vin) 56 | self.output.setText('%s' % crc) 57 | 58 | 59 | def plugin_entry(): 60 | a = CrcWidget() 61 | a.exec_() 62 | --------------------------------------------------------------------------------