コード例 #1
0
        /// <summary>
        /// Unlock the PCM by requesting a 'seed' and then sending the corresponding 'key' value.
        /// </summary>
        public async Task<bool> UnlockEcu(int keyAlgorithm)
        {
            await this.device.SetTimeout(TimeoutScenario.ReadProperty);

            this.device.ClearMessageQueue();

            this.logger.AddDebugMessage("Sending seed request.");
            Message seedRequest = this.messageFactory.CreateSeedRequest();

            if (!await this.TrySendMessage(seedRequest, "seed request"))
            {
                this.logger.AddUserMessage("Unable to send seed request.");
                return false;
            }

            bool seedReceived = false;
            UInt16 seedValue = 0;

            for (int attempt = 1; attempt < MaxReceiveAttempts; attempt++)
            {
                Message seedResponse = await this.device.ReceiveMessage();
                if (seedResponse == null)
                {
                    this.logger.AddDebugMessage("No response to seed request.");
                    return false;
                }

                if (this.messageParser.IsUnlocked(seedResponse.GetBytes()))
                {
                    this.logger.AddUserMessage("PCM is already unlocked");
                    return true;
                }

                this.logger.AddDebugMessage("Parsing seed value.");
                Response<UInt16> seedValueResponse = this.messageParser.ParseSeed(seedResponse.GetBytes());
                if (seedValueResponse.Status == ResponseStatus.Success)
                {
                    seedValue = seedValueResponse.Value;
                    seedReceived = true;
                    break;
                }

                this.logger.AddDebugMessage("Unable to parse seed response. Attempt #" + attempt.ToString());
            }

            if (!seedReceived)
            {
                this.logger.AddUserMessage("No seed reponse received, unable to unlock PCM.");
                return false;
            }

            if (seedValue == 0x0000)
            {
                this.logger.AddUserMessage("PCM Unlock not required");
                return true;
            }

            UInt16 key = KeyAlgorithm.GetKey(keyAlgorithm, seedValue);

            this.logger.AddDebugMessage("Sending unlock request (" + seedValue.ToString("X4") + ", " + key.ToString("X4") + ")");
            Message unlockRequest = this.messageFactory.CreateUnlockRequest(key);
            if (!await this.TrySendMessage(unlockRequest, "unlock request"))
            {
                this.logger.AddDebugMessage("Unable to send unlock request.");
                return false;
            }

            for (int attempt = 1; attempt < MaxReceiveAttempts; attempt++)
            {
                Message unlockResponse = await this.device.ReceiveMessage();
                if (unlockResponse == null)
                {
                    this.logger.AddDebugMessage("No response to unlock request. Attempt #" + attempt.ToString());
                    continue;
                }

                string errorMessage;
                Response<bool> result = this.messageParser.ParseUnlockResponse(unlockResponse.GetBytes(), out errorMessage);
                if (errorMessage == null)
                {
                    return result.Value;
                }

                this.logger.AddUserMessage(errorMessage);
            }

            this.logger.AddUserMessage("Unable to process unlock response.");
            return false;
        }
コード例 #2
0
 /// <summary>
 /// Suppres chatter on the VPW bus.
 /// </summary>
 public async Task SuppressChatter()
 {
     this.logger.AddDebugMessage("Suppressing VPW chatter.");
     Message suppressChatter = this.messageFactory.CreateDisableNormalMessageTransmission();
     await this.device.SendMessage(suppressChatter);
 }
コード例 #3
0
        /// <summary>
        /// Load the executable payload on the PCM at the supplied address, and execute it.
        /// </summary>
        public async Task<bool> PCMExecute(byte[] payload, int address, CancellationToken cancellationToken)
        {
            logger.AddUserMessage("Uploading kernel to PCM.");

            logger.AddDebugMessage("Sending upload request with payload size " + payload.Length + ", loadaddress " + address.ToString("X6"));
            Message request = messageFactory.CreateUploadRequest(payload.Length, address);

            if(!await TrySendMessage(request, "upload request"))
            {
                return false;
            }

            if (!await this.WaitForSuccess(this.messageParser.ParseUploadPermissionResponse))
            {
                logger.AddUserMessage("Permission to upload kernel was denied.");
                return false;
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return false;
            }

            logger.AddDebugMessage("Going to load a " + payload.Length + " byte payload to 0x" + address.ToString("X6"));

            await this.device.SetTimeout(TimeoutScenario.SendKernel);

            // Loop through the payload building and sending packets, highest first, execute on last
            int payloadSize = device.MaxSendSize - 12; // Headers use 10 bytes, sum uses 2 bytes.
            int chunkCount = payload.Length / payloadSize;
            int remainder = payload.Length % payloadSize;

            int offset = (chunkCount * payloadSize);
            int startAddress = address + offset;

            // First we send the 'remainder' payload, containing any bytes that won't fill up an entire upload packet.
            logger.AddDebugMessage(
                string.Format(
                    "Sending remainder payload with offset 0x{0:X}, start address 0x{1:X}, length 0x{2:X}.",
                    offset,
                    startAddress,
                    remainder));

            Message remainderMessage = messageFactory.CreateBlockMessage(
                payload, 
                offset, 
                remainder, 
                address + offset, 
                remainder == payload.Length);

            Response<bool> uploadResponse = await WriteToRam(remainderMessage);
            if (uploadResponse.Status != ResponseStatus.Success)
            {
                logger.AddDebugMessage("Could not upload kernel to PCM, remainder payload not accepted.");
                return false;
            }

            // Now we send a series of full upload packets
            for (int chunkIndex = chunkCount; chunkIndex > 0; chunkIndex--)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return false;
                }

                offset = (chunkIndex - 1) * payloadSize;
                startAddress = address + offset;
                Message payloadMessage = messageFactory.CreateBlockMessage(
                    payload,
                    offset,
                    payloadSize,
                    startAddress,
                    offset == 0);

                logger.AddDebugMessage(
                    string.Format(
                        "Sending payload with offset 0x{0:X}, start address 0x{1:X}, length 0x{2:X}.",
                        offset,
                        startAddress,
                        payloadSize));

                uploadResponse = await WriteToRam(payloadMessage);
                if (uploadResponse.Status != ResponseStatus.Success)
                {
                    logger.AddDebugMessage("Could not upload kernel to PCM, payload not accepted.");
                    return false;
                }

                int bytesSent = payload.Length - offset;
                int percentDone = bytesSent * 100 / payload.Length;

                this.logger.AddUserMessage(
                    string.Format(
                        "Kernel upload {0}% complete.",
                        percentDone));
            }

            return true;
        }
コード例 #4
0
        /// <summary>
        /// Does everything required to switch to VPW 4x
        /// </summary>
        public async Task<bool> VehicleSetVPW4x(VpwSpeed newSpeed)
        {
            if (!device.Supports4X) 
            {
                if (newSpeed == VpwSpeed.FourX)
                {
                    // where there is no support only report no switch to 4x
                    logger.AddUserMessage("This interface does not support VPW 4x");
                }
                return true;
            }
            
            // Configure the vehicle bus when switching to 4x
            if (newSpeed == VpwSpeed.FourX)
            {
                logger.AddUserMessage("Attempting switch to VPW 4x");
                await device.SetTimeout(TimeoutScenario.ReadProperty);

                // The list of modules may not be useful after all, but 
                // checking for an empty list indicates an uncooperative
                // module on the VPW bus.
                List<byte> modules = await this.RequestHighSpeedPermission();
                if (modules == null)
                {
                    // A device has refused the switch to high speed mode.
                    return false;
                }

                Message broadcast = this.messageFactory.CreateBeginHighSpeed(DeviceId.Broadcast);
                await this.device.SendMessage(broadcast);

                // Check for any devices that refused to switch to 4X speed.
                // These responses usually get lost, so this code might be pointless.
                Message response = null;
                while ((response = await this.device.ReceiveMessage()) != null)
                {
                    Response<bool> refused = this.messageParser.ParseHighSpeedRefusal(response);
                    if (refused.Status != ResponseStatus.Success)
                    {
                        continue;
                    }

                    if (refused.Value == false)
                    {
                        // TODO: Add module number.
                        this.logger.AddUserMessage("Module refused high-speed switch.");
                        return false;
                    }
                }
            }
            else
            {
                logger.AddUserMessage("Reverting to VPW 1x");
            }

            // Request the device to change
            await device.SetVpwSpeed(newSpeed);

            TimeoutScenario scenario = newSpeed == VpwSpeed.Standard ? TimeoutScenario.ReadProperty : TimeoutScenario.ReadMemoryBlock;
            await device.SetTimeout(scenario);

            return true;
        }
コード例 #5
0
        private async Task<bool> TryReadBlock(byte[] image, int length, int startAddress)
        {
            this.logger.AddDebugMessage(string.Format("Reading from {0}, length {1}", startAddress, length));
            
            for(int sendAttempt = 1; sendAttempt <= MaxSendAttempts; sendAttempt++)
            {
                Message message = this.messageFactory.CreateReadRequest(startAddress, length);

                //this.logger.AddDebugMessage("Sending " + message.GetBytes().ToHex());
                if (!await this.device.SendMessage(message))
                {
                    this.logger.AddDebugMessage("Unable to send read request.");
                    continue;
                }

                bool sendAgain = false;
                for (int receiveAttempt = 1; receiveAttempt <= MaxReceiveAttempts; receiveAttempt++)
                {
                    Message response = await this.ReceiveMessage();
                    if (response == null)
                    {
                        this.logger.AddDebugMessage("Did not receive a response to the read request.");
                        sendAgain = true;
                        break;
                    }

                    this.logger.AddDebugMessage("Processing message");

                    Response<bool> readResponse = this.messageParser.ParseReadResponse(response);
                    if (readResponse.Status != ResponseStatus.Success)
                    {
                        this.logger.AddDebugMessage("Not a read response.");
                        continue;
                    }

                    if (!readResponse.Value)
                    {
                        this.logger.AddDebugMessage("Read request failed.");
                        sendAgain = true;
                        break;
                    }

                    // We got a successful read response, so now wait for the payload.
                    sendAgain = false;
                    break;
                }

                if (sendAgain)
                {
                    continue;
                }

                this.logger.AddDebugMessage("Read request allowed, expecting for payload...");
                for (int receiveAttempt = 1; receiveAttempt <= MaxReceiveAttempts; receiveAttempt++)
                {   
                    Message payloadMessage = await this.device.ReceiveMessage();
                    if (payloadMessage == null)
                    {
                        this.logger.AddDebugMessage("No payload following read request.");
                        continue;
                    }

                    this.logger.AddDebugMessage("Processing message");

                    Response<byte[]> payloadResponse = this.messageParser.ParsePayload(payloadMessage, length, startAddress);
                    if (payloadResponse.Status != ResponseStatus.Success)
                    {
                        this.logger.AddDebugMessage("Not a valid payload message or bad checksum");
                        continue;
                    }

                    byte[] payload = payloadResponse.Value;
                    Buffer.BlockCopy(payload, 0, image, startAddress, length);

                    int percentDone = (startAddress * 100) / image.Length;
                    this.logger.AddUserMessage(string.Format("Recieved block starting at {0} / 0x{0:X}. {1}%", startAddress, percentDone));

                    return true;
                }
            }

            return false;
        }