Ejemplo n.º 1
0
        private void UnlockControllerForEepromReadWrite(IKW1281Dialog kwp1281)
        {
            switch ((ControllerAddress)_controllerAddress)
            {
            case ControllerAddress.CCM:
            case ControllerAddress.CentralLocking:
                kwp1281.Login(code: 19283, workshopCode: 222);     // This is what VDS-PRO uses
                break;

            case ControllerAddress.Cluster:
                // TODO:UnlockCluster() is only needed for EEPROM read, not memory read
                if (!VdoCluster.UnlockCluster(kwp1281))
                {
                    Logger.WriteLine("Unknown cluster software version. EEPROM access will likely fail.");
                }

                if (!ClusterRequiresSeedKey(kwp1281))
                {
                    Logger.WriteLine(
                        "Cluster is unlocked for EEPROM access. Skipping Seed/Key login.");
                    return;
                }

                ClusterSeedKeyAuthenticate(kwp1281);
                break;
            }
        }
Ejemplo n.º 2
0
        private void ClarionVWPremium4SafeCode(IKW1281Dialog kwp1281)
        {
            if (_controllerAddress != (int)ControllerAddress.Radio)
            {
                Logger.WriteLine("Only supported for radio address 56");
                return;
            }

            // Thanks to Mike Naberezny for this (https://github.com/mnaberez)
            const byte readWriteSafeCode = 0xF0;
            const byte read = 0x00;

            kwp1281.SendBlock(new List <byte> {
                readWriteSafeCode, read
            });

            var block = kwp1281.ReceiveBlocks().FirstOrDefault(b => !b.IsAckNak);

            if (block == null)
            {
                Logger.WriteLine("No response received from radio.");
            }
            else if (block.Title != readWriteSafeCode)
            {
                Logger.WriteLine(
                    $"Unexpected response received from radio. Block title: ${block.Title:X2}");
            }
            else
            {
                var safeCode = block.Body[0] * 256 + block.Body[1];
                Logger.WriteLine($"Safe code: {safeCode:X4}");
            }
        }
Ejemplo n.º 3
0
        private static void ClusterSeedKeyAuthenticate(IKW1281Dialog kwp1281)
        {
            // Perform Seed/Key authentication
            Logger.WriteLine("Sending Custom \"Seed request\" block");
            var response = kwp1281.SendCustom(new List <byte> {
                0x96, 0x01
            });

            var responseBlocks = response.Where(b => !b.IsAckNak).ToList();

            if (responseBlocks.Count == 1 && responseBlocks[0] is CustomBlock customBlock)
            {
                Logger.WriteLine($"Block: {Utils.Dump(customBlock.Body)}");

                var keyBytes = VdoKeyFinder.FindKey(customBlock.Body.ToArray());

                Logger.WriteLine("Sending Custom \"Key response\" block");

                var keyResponse = new List <byte> {
                    0x96, 0x02
                };
                keyResponse.AddRange(keyBytes);

                response = kwp1281.SendCustom(keyResponse);
            }
        }
Ejemplo n.º 4
0
        // Begin top-level commands

        private static void ActuatorTest(IKW1281Dialog kwp1281)
        {
            using KW1281KeepAlive keepAlive = new(kwp1281);

            ConsoleKeyInfo keyInfo;

            do
            {
                var response = keepAlive.ActuatorTest(0x00);
                if (response == null || response.ActuatorName == "End")
                {
                    Logger.WriteLine("End of test.");
                    break;
                }
                Logger.WriteLine($"Actuator Test: {response.ActuatorName}");

                // Press any key to advance to next test or press Q to exit
                Console.Write("Press 'N' to advance to next test or 'Q' to quit");
                do
                {
                    keyInfo = Console.ReadKey(intercept: true);
                } while (keyInfo.Key != ConsoleKey.N && keyInfo.Key != ConsoleKey.Q);
                Console.WriteLine();
            } while (keyInfo.Key != ConsoleKey.Q);
        }
Ejemplo n.º 5
0
        private void DumpClusterMem(IKW1281Dialog kwp1281, uint startAddress, uint length)
        {
            UnlockControllerForEepromReadWrite(kwp1281);

            const byte blockSize = 15;

            var dumpFileName = _filename ?? $"cluster_mem_${startAddress:X6}.bin";

            Logger.WriteLine($"Saving memory dump to {dumpFileName}");
            using (var fs = File.Create(dumpFileName, blockSize, FileOptions.WriteThrough))
            {
                for (uint addr = startAddress; addr < startAddress + length; addr += blockSize)
                {
                    var readLength = (byte)Math.Min(startAddress + length - addr, blockSize);
                    var blockBytes = kwp1281.CustomReadMemory(addr, readLength);
                    if (blockBytes.Count != readLength)
                    {
                        throw new InvalidOperationException(
                                  $"Expected {readLength} bytes from CustomReadMemory() but received {blockBytes.Count} bytes");
                    }
                    fs.Write(blockBytes.ToArray(), 0, blockBytes.Count);
                    fs.Flush();
                }
            }
            Logger.WriteLine($"Saved memory dump to {dumpFileName}");
        }
Ejemplo n.º 6
0
        private static void DumpEeprom(
            IKW1281Dialog kwp1281, ushort startAddr, ushort length, byte maxReadLength, string fileName)
        {
            bool succeeded = true;

            using (var fs = File.Create(fileName, maxReadLength, FileOptions.WriteThrough))
            {
                for (uint addr = startAddr; addr < (startAddr + length); addr += maxReadLength)
                {
                    var readLength = (byte)Math.Min(startAddr + length - addr, maxReadLength);
                    var blockBytes = kwp1281.ReadEeprom((ushort)addr, (byte)readLength);
                    if (blockBytes == null)
                    {
                        blockBytes = Enumerable.Repeat((byte)0, readLength).ToList();
                        succeeded  = false;
                    }
                    fs.Write(blockBytes.ToArray(), 0, blockBytes.Count);
                    fs.Flush();
                }
            }

            if (!succeeded)
            {
                Logger.WriteLine();
                Logger.WriteLine("**********************************************************************");
                Logger.WriteLine("*** Warning: Some bytes could not be read and were replaced with 0 ***");
                Logger.WriteLine("**********************************************************************");
                Logger.WriteLine();
            }
        }
Ejemplo n.º 7
0
 private static void ReadIdent(IKW1281Dialog kwp1281)
 {
     foreach (var identInfo in kwp1281.ReadIdent())
     {
         Logger.WriteLine($"Ident: {identInfo}");
     }
 }
Ejemplo n.º 8
0
        private void WriteEeprom(IKW1281Dialog kwp1281, uint address, byte value)
        {
            UnlockControllerForEepromReadWrite(kwp1281);

            kwp1281.WriteEeprom((ushort)address, new List <byte> {
                value
            });
        }
Ejemplo n.º 9
0
        private void LoadEeprom(IKW1281Dialog kwp1281, uint address)
        {
            if (_controllerAddress != (int)ControllerAddress.Cluster)
            {
                Logger.WriteLine("Only supported for cluster");
                return;
            }

            LoadClusterEeprom(kwp1281, (ushort)address, _filename);
        }
Ejemplo n.º 10
0
        private void DumpMem(IKW1281Dialog kwp1281, uint address, uint length)
        {
            if (_controllerAddress != (int)ControllerAddress.Cluster)
            {
                Logger.WriteLine("Only supported for cluster");
                return;
            }

            DumpClusterMem(kwp1281, address, length);
        }
Ejemplo n.º 11
0
        private void DumpCcmEeprom(IKW1281Dialog kwp1281, ushort startAddress, ushort length)
        {
            UnlockControllerForEepromReadWrite(kwp1281);

            var dumpFileName = _filename ?? $"ccm_eeprom_${startAddress:X4}.bin";

            Logger.WriteLine($"Saving EEPROM dump to {dumpFileName}");
            DumpEeprom(kwp1281, startAddress, length, maxReadLength: 12, dumpFileName);
            Logger.WriteLine($"Saved EEPROM dump to {dumpFileName}");
        }
Ejemplo n.º 12
0
        private static void ReadFaultCodes(IKW1281Dialog kwp1281)
        {
            var faultCodes = kwp1281.ReadFaultCodes();

            Logger.WriteLine("Fault codes:");
            foreach (var faultCode in faultCodes)
            {
                Logger.WriteLine($"    {faultCode}");
            }
        }
Ejemplo n.º 13
0
 private void Reset(IKW1281Dialog kwp1281)
 {
     if (_controllerAddress == (int)ControllerAddress.Cluster)
     {
         kwp1281.CustomReset();
     }
     else
     {
         Logger.WriteLine("Only supported for cluster");
     }
 }
Ejemplo n.º 14
0
        private void DumpCcmRom(IKW1281Dialog kwp1281)
        {
            if (_controllerAddress != (int)ControllerAddress.CCM &&
                _controllerAddress != (int)ControllerAddress.CentralLocking)
            {
                Logger.WriteLine("Only supported for CCM and Central Locking");
                return;
            }

            kwp1281.Login(19283, 222);

            var        dumpFileName = _filename ?? "ccm_rom_dump.bin";
            const byte blockSize    = 8;

            Logger.WriteLine($"Saving CCM ROM to {dumpFileName}");

            bool succeeded = true;

            using (var fs = File.Create(dumpFileName, blockSize, FileOptions.WriteThrough))
            {
                for (int seg = 0; seg < 16; seg++)
                {
                    for (int msb = 0; msb < 16; msb++)
                    {
                        for (int lsb = 0; lsb < 256; lsb += blockSize)
                        {
                            var blockBytes = kwp1281.ReadCcmRom((byte)seg, (byte)msb, (byte)lsb, blockSize);
                            if (blockBytes == null)
                            {
                                blockBytes = Enumerable.Repeat((byte)0, blockSize).ToList();
                                succeeded  = false;
                            }
                            else if (blockBytes.Count < blockSize)
                            {
                                blockBytes.AddRange(Enumerable.Repeat((byte)0, blockSize - blockBytes.Count));
                                succeeded = false;
                            }

                            fs.Write(blockBytes.ToArray(), 0, blockBytes.Count);
                            fs.Flush();
                        }
                    }
                }
            }

            if (!succeeded)
            {
                Logger.WriteLine();
                Logger.WriteLine("**********************************************************************");
                Logger.WriteLine("*** Warning: Some bytes could not be read and were replaced with 0 ***");
                Logger.WriteLine("**********************************************************************");
                Logger.WriteLine();
            }
        }
Ejemplo n.º 15
0
        private void DumpClusterEeprom(IKW1281Dialog kwp1281, ushort startAddress, ushort length)
        {
            var identInfo = kwp1281.ReadIdent().First().ToString().Replace(' ', '_').Replace(":", "");

            UnlockControllerForEepromReadWrite(kwp1281);

            var dumpFileName = _filename ?? $"{identInfo}_${startAddress:X4}_eeprom.bin";

            Logger.WriteLine($"Saving EEPROM dump to {dumpFileName}");
            DumpEeprom(kwp1281, startAddress, length, maxReadLength: 16, dumpFileName);
            Logger.WriteLine($"Saved EEPROM dump to {dumpFileName}");
        }
Ejemplo n.º 16
0
        private void ClearFaultCodes(IKW1281Dialog kwp1281)
        {
            var succeeded = kwp1281.ClearFaultCodes(_controllerAddress);

            if (succeeded)
            {
                Logger.WriteLine("Fault codes cleared.");
            }
            else
            {
                Logger.WriteLine("Failed to clear fault codes.");
            }
        }
Ejemplo n.º 17
0
        private void SetSoftwareCoding(
            IKW1281Dialog kwp1281, int softwareCoding, int workshopCode)
        {
            var succeeded = kwp1281.SetSoftwareCoding(_controllerAddress, softwareCoding, workshopCode);

            if (succeeded)
            {
                Logger.WriteLine("Software coding set.");
            }
            else
            {
                Logger.WriteLine("Failed to set software coding.");
            }
        }
Ejemplo n.º 18
0
        private string DumpClusterEeprom(IKW1281Dialog kwp1281, ushort startAddress, ushort length)
        {
            var identInfo = kwp1281.ReadIdent().First().ToString()
                            .Split(Environment.NewLine).First() // Sometimes ReadIdent() can return multiple lines
                            .Replace(' ', '_').Replace(":", "");

            UnlockControllerForEepromReadWrite(kwp1281);

            var dumpFileName = _filename ?? $"{identInfo}_${startAddress:X4}_eeprom.bin";

            Logger.WriteLine($"Saving EEPROM dump to {dumpFileName}");
            DumpEeprom(kwp1281, startAddress, length, maxReadLength: 16, dumpFileName);
            Logger.WriteLine($"Saved EEPROM dump to {dumpFileName}");

            return(dumpFileName);
        }
Ejemplo n.º 19
0
        private void DumpClusterNecRom(IKW1281Dialog kwp1281)
        {
            if (_controllerAddress != (int)ControllerAddress.Cluster)
            {
                Logger.WriteLine("Only supported for cluster");
                return;
            }

            var        dumpFileName = _filename ?? "cluster_nec_rom_dump.bin";
            const byte blockSize    = 16;

            Logger.WriteLine($"Saving cluster NEC ROM to {dumpFileName}");

            bool succeeded = true;

            using (var fs = File.Create(dumpFileName, blockSize, FileOptions.WriteThrough))
            {
                {
                    for (int address = 0; address < 65536; address += blockSize)
                    {
                        var blockBytes = kwp1281.CustomReadNecRom((ushort)address, blockSize);
                        if (blockBytes == null)
                        {
                            blockBytes = Enumerable.Repeat((byte)0, blockSize).ToList();
                            succeeded  = false;
                        }
                        else if (blockBytes.Count < blockSize)
                        {
                            blockBytes.AddRange(Enumerable.Repeat((byte)0, blockSize - blockBytes.Count));
                            succeeded = false;
                        }

                        fs.Write(blockBytes.ToArray(), 0, blockBytes.Count);
                        fs.Flush();
                    }
                }
            }

            if (!succeeded)
            {
                Logger.WriteLine();
                Logger.WriteLine("**********************************************************************");
                Logger.WriteLine("*** Warning: Some bytes could not be read and were replaced with 0 ***");
                Logger.WriteLine("**********************************************************************");
                Logger.WriteLine();
            }
        }
Ejemplo n.º 20
0
        private void ReadEeprom(IKW1281Dialog kwp1281, uint address)
        {
            UnlockControllerForEepromReadWrite(kwp1281);

            var blockBytes = kwp1281.ReadEeprom((ushort)address, 1);

            if (blockBytes == null)
            {
                Logger.WriteLine("EEPROM read failed");
            }
            else
            {
                var value = blockBytes[0];
                Logger.WriteLine(
                    $"Address {address} (${address:X4}): Value {value} (${value:X2})");
            }
        }
Ejemplo n.º 21
0
        private void LoadClusterEeprom(IKW1281Dialog kwp1281, ushort address, string filename)
        {
            _ = kwp1281.ReadIdent();

            UnlockControllerForEepromReadWrite(kwp1281);

            if (!File.Exists(filename))
            {
                Logger.WriteLine($"File {filename} does not exist.");
                return;
            }

            Logger.WriteLine($"Reading {filename}");
            var bytes = File.ReadAllBytes(filename);

            Logger.WriteLine("Writing to cluster...");
            WriteEeprom(kwp1281, address, bytes, 16);
        }
Ejemplo n.º 22
0
        private void DumpEeprom(IKW1281Dialog kwp1281, uint address, uint length)
        {
            switch (_controllerAddress)
            {
            case (int)ControllerAddress.Cluster:
                DumpClusterEeprom(kwp1281, (ushort)address, (ushort)length);
                break;

            case (int)ControllerAddress.CCM:
            case (int)ControllerAddress.CentralLocking:
                DumpCcmEeprom(kwp1281, (ushort)address, (ushort)length);
                break;

            default:
                Logger.WriteLine("Only supported for cluster, CCM and Central Locking");
                break;
            }
        }
Ejemplo n.º 23
0
        private void MapEeprom(IKW1281Dialog kwp1281)
        {
            switch (_controllerAddress)
            {
            case (int)ControllerAddress.Cluster:
                MapClusterEeprom(kwp1281);
                break;

            case (int)ControllerAddress.CCM:
            case (int)ControllerAddress.CentralLocking:
                MapCcmEeprom(kwp1281);
                break;

            default:
                Logger.WriteLine("Only supported for cluster, CCM and Central Locking");
                break;
            }
        }
Ejemplo n.º 24
0
        private void DelcoVWPremium5SafeCode(IKW1281Dialog kwp1281)
        {
            if (_controllerAddress != (int)ControllerAddress.RadioManufacturing)
            {
                Logger.WriteLine("Only supported for radio manufacturing address 7C");
                return;
            }

            // Thanks to Mike Naberezny for this (https://github.com/mnaberez)
            const string secret       = "DELCO";
            var          code         = (ushort)(secret[4] * 256 + secret[3]);
            var          workshopCode = (ushort)(secret[1] * 256 + secret[0]);
            var          unknown      = (byte)secret[2];

            kwp1281.Login(code, workshopCode, unknown);
            var bytes = kwp1281.ReadRomEeprom(0x0014, 2);

            Logger.WriteLine($"Safe code: {bytes[0]:X2}{bytes[1]:X2}");
        }
Ejemplo n.º 25
0
        private static bool ClusterRequiresSeedKey(IKW1281Dialog kwp1281)
        {
            Logger.WriteLine("Sending Custom \"Need Seed/Key?\" block");
            var response = kwp1281.SendCustom(new List <byte> {
                0x96, 0x04
            });
            var responseBlocks = response.Where(b => !b.IsAckNak).ToList();

            if (responseBlocks.Count == 1 && responseBlocks[0] is CustomBlock)
            {
                // Custom 0x04 means need to do Seed/Key
                // Custom 0x07 means unlocked
                if (responseBlocks[0].Body.First() == 0x07)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 26
0
        private void MapCcmEeprom(IKW1281Dialog kwp1281)
        {
            kwp1281.Login(19283, 222);

            var        bytes     = new List <byte>();
            const byte blockSize = 1;

            for (int addr = 0; addr <= 65535; addr += blockSize)
            {
                var blockBytes = kwp1281.ReadEeprom((ushort)addr, blockSize);
                blockBytes = Enumerable.Repeat(
                    blockBytes == null ? (byte)0 : (byte)0xFF,
                    blockSize).ToList();
                bytes.AddRange(blockBytes);
            }
            var dumpFileName = _filename ?? "ccm_eeprom_map.bin";

            Logger.WriteLine($"Saving EEPROM map to {dumpFileName}");
            File.WriteAllBytes(dumpFileName, bytes.ToArray());
        }
Ejemplo n.º 27
0
        public static bool UnlockCluster(IKW1281Dialog kwp1281)
        {
            var versionBlocks = kwp1281.CustomReadSoftwareVersion();

            // Now we need to send an unlock code that is unique to each ROM version
            Logger.WriteLine("Sending Custom \"Unlock partial EEPROM read\" block");
            var softwareVersion = versionBlocks[0].Body;
            var unlockCodes     = GetClusterUnlockCodes(softwareVersion);
            var unlocked        = false;

            foreach (var unlockCode in unlockCodes)
            {
                var unlockCommand = new List <byte> {
                    0x9D
                };
                unlockCommand.AddRange(unlockCode);
                var unlockResponse = kwp1281.SendCustom(unlockCommand);
                if (unlockResponse.Count != 1)
                {
                    throw new InvalidOperationException(
                              $"Received multiple responses from unlock request.");
                }
                if (unlockResponse[0].IsAck)
                {
                    Logger.WriteLine(
                        $"Unlock code for software version {KW1281Dialog.DumpMixedContent(softwareVersion)} is {Utils.Dump(unlockCode)}");
                    if (unlockCodes.Length > 1)
                    {
                        Logger.WriteLine("Please report this to the program maintainer.");
                    }
                    unlocked = true;
                    break;
                }
                else if (!unlockResponse[0].IsNak)
                {
                    throw new InvalidOperationException(
                              $"Received non-ACK/NAK ${unlockResponse[0].Title:X2} from unlock request.");
                }
            }
            return(unlocked);
        }
Ejemplo n.º 28
0
        private static void WriteEeprom(
            IKW1281Dialog kwp1281, ushort startAddr, byte[] bytes, uint maxWriteLength)
        {
            var succeeded = true;
            var length    = bytes.Length;

            for (uint addr = startAddr; addr < (startAddr + length); addr += maxWriteLength)
            {
                var writeLength = (byte)Math.Min(startAddr + length - addr, maxWriteLength);
                if (!kwp1281.WriteEeprom(
                        (ushort)addr,
                        bytes.Skip((int)(addr - startAddr)).Take(writeLength).ToList()))
                {
                    succeeded = false;
                }
            }

            if (!succeeded)
            {
                Logger.WriteLine("EEPROM write failed. You should probably try again.");
            }
        }
Ejemplo n.º 29
0
        // End top-level commands

        private void MapClusterEeprom(IKW1281Dialog kwp1281)
        {
            // Unlock partial EEPROM read
            _ = kwp1281.SendCustom(new List <byte> {
                0x9D, 0x39, 0x34, 0x34, 0x40
            });

            var        bytes     = new List <byte>();
            const byte blockSize = 1;

            for (ushort addr = 0; addr < 2048; addr += blockSize)
            {
                var blockBytes = kwp1281.ReadEeprom(addr, blockSize);
                blockBytes = Enumerable.Repeat(
                    blockBytes == null ? (byte)0 : (byte)0xFF,
                    blockSize).ToList();
                bytes.AddRange(blockBytes);
            }
            var dumpFileName = _filename ?? "eeprom_map.bin";

            Logger.WriteLine($"Saving EEPROM map to {dumpFileName}");
            File.WriteAllBytes(dumpFileName, bytes.ToArray());
        }
Ejemplo n.º 30
0
 private static void ReadSoftwareVersion(IKW1281Dialog kwp1281)
 {
     kwp1281.CustomReadSoftwareVersion();
 }