Beispiel #1
0
        /// <summary>
        /// Parse the replies checking for a valid response, if we have a valid response extract the payload data
        /// </summary>
        /// <param name="rxMsgs"></param>
        /// <param name="txMode"></param>
        /// <param name="payload"></param>
        /// <returns></returns>
        UDSPacket ParseUDSResponse(PassThruMsg rxMsg, UDScmd.Mode txMode)
        {
            var       rxMsgBytes = rxMsg.GetBytes();
            UDSPacket rxPacket   = new UDSPacket();
            //Iterate the reply bytes to find the echod ECU index, response code, function response and payload data if there is any
            //If we could use some kind of HEX regex this would be a bit neater
            int stateMachine = 0;

            for (int i = 0; i < rxMsgBytes.Length; i++)
            {
                switch (stateMachine)
                {
                case 0:
                    if (rxMsgBytes[i] == 0x07)
                    {
                        stateMachine = 1;
                    }
                    else if (rxMsgBytes[i] != 0)
                    {
                        return(rxPacket);
                    }
                    break;

                case 1:
                    if (rxMsgBytes[i] == 0xE8)
                    {
                        stateMachine = 2;
                    }
                    else
                    {
                        return(rxPacket);
                    }
                    break;

                case 2:
                    var payload = new byte[rxMsgBytes.Length - i];

                    int payloadLength = rxMsgBytes.Length - i;
                    if (payloadLength > 0)
                    {
                        payload = new byte[payloadLength];
                        Array.Copy(rxMsgBytes, i, payload, 0, payloadLength);
                        rxPacket = new UDSPacket(payload, txMode);
                        ;
                    }
                    return(rxPacket);

                case 3:
                default:
                    return(rxPacket);
                }
            }
            return(rxPacket);
        }
Beispiel #2
0
        public void ReadMemoryByAddress(uint address, uint blockSize, out byte[] memory)
        {
            //Send the read memory request
            byte blockSizeUpper = (byte)((blockSize >> 8) & 0xFF);
            byte blockSizeLower = (byte)(blockSize & 0xFF);

            //ISO14229 ReadMemoryByAddress
            //byte1 ServiceID 0x23
            //byte2 AddressAndLengthFormatIdentifier (0 for Ford Spanish Oak)
            //byte3 address byte 1
            //byte4 address byte 2
            //byte5 address byte 3
            //byte6 address byte 4
            //byte7 block size byte1
            //byte8 block size byte2
            byte[] txMsgBytes = { (byte)UDScmd.Mode.READ_MEMORY_BY_ADDRESS, 0, (byte)((address >> 16) & 0xFF), (byte)((address >> 8) & 0xFF), (byte)((address) & 0xFF), blockSizeUpper, blockSizeLower };
            SendMessage(txMsgBytes);

            //We expect 3 messages, rx, start of message, then the payload data
            List <PassThruMsg> rxMsgs;

            //This will throw an exception if we don't get a valid reply
            while (ReadMessage(out rxMsgs, 250) == J2534Err.STATUS_NOERROR)
            {
                if (rxMsgs[0].RxStatus == RxStatus.NONE)
                {
                    break;
                }
            }

            //If we couldn't find the start of the mesage give up
            if (J2534Status != J2534Err.STATUS_NOERROR)
            {
                throw new J2534Exception(J2534Status);
            }
            if (rxMsgs.Count < 1)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }

            UDSPacket rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.READ_MEMORY_BY_ADDRESS);

            if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
            {
                throw new UDSException(rxPacket.NegativeResponse);
            }
            memory = rxPacket.Payload;
        }
Beispiel #3
0
        public void RequestTransferExit()
        {
            //ISO14229 RequestTransferExit
            //byte1 ServiceID 0x37

            byte[] txMsgBytes = { (byte)UDScmd.Mode.TRANSFER_EXIT };
            SendMessage(txMsgBytes);

            //We expect no reply
            List <PassThruMsg> rxMsgs;

            //This will throw an exception if we don't get a valid reply
            while (ReadMessage(out rxMsgs, 250) == J2534Err.STATUS_NOERROR)
            {
                if (rxMsgs[0].RxStatus == RxStatus.NONE)
                {
                    break;
                }
            }

            //If we couldn't find the start of the mesage give up
            if (J2534Status != J2534Err.STATUS_NOERROR)
            {
                throw new J2534Exception(J2534Status);
            }
            if (rxMsgs.Count < 1)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }

            UDSPacket rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.TRANSFER_EXIT);
            var       b        = rxMsgs[0].GetBytes();

            if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
            {
                //We expect a negative response but with response pending
                if (rxPacket.NegativeResponse != UDScmd.NegativeResponse.REPONSE_PENDING)
                {
                    throw new UDSException(rxPacket.NegativeResponse);
                }
            }
        }
Beispiel #4
0
        public void SecurityAccess(byte subFunction)
        {
            //Send the security request
            byte[] txMsgBytes = { (byte)UDScmd.Mode.SECURITY_ACCESS, subFunction };
            SendMessage(txMsgBytes);

            //Attempt to read at least 1 message as a reply
            List <PassThruMsg> rxMsgs;

            ReadAllMessages(out rxMsgs, 1, 200);

            //Find the start of the response and parse it.
            PassThruMsg seedKeyResponse;
            int         startOfMessageIndex = GetStartOfMessageIndex(rxMsgs);

            if (startOfMessageIndex == -1)
            {
                throw new J2534Exception(J2534Err.ERR_BUFFER_EMPTY);
            }
            seedKeyResponse = rxMsgs[startOfMessageIndex];

            //needs to respond with 00 00 07 e8 67 03 xx xx xx
            //response is 00 00 7F 27 12 if you have just powered on and had VPP during power on but the command is incorrect length (unsupported)
            //response is 00 00 7F 27 11 if you have no VPP
            //response is 00 07 E8 67 mode XX XX XX if success
            UDSPacket rxPacket = ParseUDSResponse(seedKeyResponse, UDScmd.Mode.SECURITY_ACCESS);

            if (rxPacket.Response == UDScmd.Response.NO_RESPONSE)
            {
                throw new UDSException(UDScmd.NegativeResponse.INCORRECT_MSG_LENGTH_OR_FORMAT);
            }
            else if (rxPacket.Response == UDScmd.Response.NEGATIVE_RESPONSE)
            {
                //Inform the user of the error
                if (rxPacket.NegativeResponse == UDScmd.NegativeResponse.UNKNOWN)
                {
                    //no error code supplied, something else went wrong
                    throw new UDSException(UDScmd.NegativeResponse.INCORRECT_MSG_LENGTH_OR_FORMAT);
                }
                else
                {
                    //We got a sub function error code
                    throw new UDSException(rxPacket.NegativeResponse);
                }
            }
            else
            {
                if (rxPacket.Payload.Length < 3)
                {
                    //Incorrect seed response length
                    throw new UDSException(UDScmd.NegativeResponse.INCORRECT_MSG_LENGTH_OR_FORMAT);
                }
                else
                {
                    //Calculate the seed response
                    var seedresponse = CalculateResponseFromSeed(0x7E0, subFunction, rxPacket.Payload);

                    //Send the packet
                    txMsgBytes = new byte[] { (byte)UDScmd.Mode.SECURITY_ACCESS, (byte)(subFunction + 1), (byte)((seedresponse >> 16) & 0xFF), (byte)((seedresponse >> 8) & 0xFF), (byte)((seedresponse) & 0xFF) };
                    SendMessage(txMsgBytes);

                    //Attempt to read at least 1 message as a reply
                    ReadAllMessages(out rxMsgs, 1, 200);

                    //Get the response
                    startOfMessageIndex = GetStartOfMessageIndex(rxMsgs);
                    if (startOfMessageIndex == -1)
                    {
                        throw new J2534Exception(J2534Err.ERR_BUFFER_EMPTY);
                    }

                    var unlockResponse = rxMsgs[startOfMessageIndex];
                    //needs to be 00 00 07 E8 67 04 (mode+1)  (or 67 02)

                    rxPacket = ParseUDSResponse(unlockResponse, UDScmd.Mode.SECURITY_ACCESS);
                    if (rxPacket.Response == UDScmd.Response.NO_RESPONSE)
                    {
                        throw new UDSException(UDScmd.NegativeResponse.INCORRECT_MSG_LENGTH_OR_FORMAT);
                    }
                    else if (rxPacket.Response == UDScmd.Response.NEGATIVE_RESPONSE)
                    {
                        //Inform the user of the error
                        if (rxPacket.NegativeResponse == UDScmd.NegativeResponse.UNKNOWN)
                        {
                            //no error code supplied, something else went wrong
                            throw new UDSException(UDScmd.NegativeResponse.INCORRECT_MSG_LENGTH_OR_FORMAT);
                        }
                        else
                        {
                            //We got a sub function error code
                            throw new UDSException(rxPacket.NegativeResponse);
                        }
                    }

                    if (rxPacket.SubFunction != subFunction + 1)
                    {
                        throw new Exception($"Returned an incorrect subfunction code, expected {subFunction+1} got {rxPacket.SubFunction}");
                    }

                    //We successfully entered the serurity level!
                }
            }
        }
Beispiel #5
0
        public void RequestDownload()
        {
            //ISO14229 RequestDownload
            //byte1 ServiceID 0x34
            //byte2 DataFormatIdentifier
            //      High nibble = memorySize)
            //      Low nibble  = memoryAddress
            //byte3 AddressAndLengthFormatIdentifier (0x01 for Ford Spanish Oak)
            //byte4 memoryAddressByte1
            //byte5 memoryAddressByte2
            //byte6 memoryAddressByte3
            //byte7 uncompressedMemorySizeByte1
            //byte8 uncompressedMemorySizeByte1
            //byte9 uncompressedMemorySizeByte1

            //We need to do something more clever here based upon the flash size
            byte[] txMsgBytes = { (byte)UDScmd.Mode.REQUEST_DOWNLOAD, 0x00, 0x01, 0x00, 00, 00, 0x0F, 0x00, 00 };
            SendMessage(txMsgBytes);

            //We expect 3 messages, rx, start of message, 0x78 (response pending) then the successful response
            List <PassThruMsg> rxMsgs;

            //This will throw an exception if we don't get a valid reply
            while (ReadMessage(out rxMsgs, 250) == J2534Err.STATUS_NOERROR)
            {
                if (rxMsgs[0].RxStatus == RxStatus.NONE)
                {
                    break;
                }
            }

            //If we couldn't find the start of the mesage give up
            if (J2534Status != J2534Err.STATUS_NOERROR)
            {
                throw new J2534Exception(J2534Status);
            }
            if (rxMsgs.Count < 1)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }

            UDSPacket rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.REQUEST_DOWNLOAD);

            if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
            {
                //We expect a negative response but with response pending
                if (rxPacket.NegativeResponse != UDScmd.NegativeResponse.REPONSE_PENDING)
                {
                    throw new UDSException(rxPacket.NegativeResponse);
                }

                //ReadMessage(out rxMsgs, 250);
                List <byte[]> temp = new List <byte[]>();
                while (ReadMessage(out rxMsgs, 250) == J2534Err.STATUS_NOERROR)
                {
                    var b = rxMsgs[0].GetBytes();
                    temp.Add(b);
                    if (rxMsgs[0].RxStatus == RxStatus.NONE)
                    {
                        break;
                    }
                }

                //If we couldn't find the start of the mesage give up
                if (J2534Status != J2534Err.STATUS_NOERROR)
                {
                    throw new J2534Exception(J2534Status);
                }
                if (rxMsgs.Count < 1)
                {
                    throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
                }

                rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.REQUEST_DOWNLOAD);
                if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
                {
                    throw new UDSException(rxPacket.NegativeResponse);
                }
            }

            //We have a positive response lets check the payload
            //This reply from the spanish oak doesn't really seem to match the ISO14229 spec however it must be in this format so we fail if it is not
            if (rxPacket.LengthFormatIdentifier != 0x04 || rxPacket.MaxNumberOfBlockLength != 0x01)
            {
                throw new UDSException(UDScmd.NegativeResponse.UPLOAD_DOWNLOAD_NOT_ACCEPTED);
            }
        }
Beispiel #6
0
        public void TransferData(byte [] data, int offset, int length, int blockSize = -1)
        {
            //ISO14229 TransferData
            //byte1 ServiceID 0x36
            if (blockSize == -1)
            {
                blockSize = length;
            }

            byte[] txMsgBytes = new byte[(length + 1)];
            txMsgBytes[0] = (byte)UDScmd.Mode.TRANSFER_DATA;
            Buffer.BlockCopy(data, offset, txMsgBytes, 1, blockSize);
            SendMessage(txMsgBytes);


            //We expect no reply
            List <PassThruMsg> rxMsgs;
            List <byte[]>      msgs = new List <byte[]>();

            //This will throw an exception if we don't get a valid reply
            while (ReadMessage(out rxMsgs, 250) == J2534Err.STATUS_NOERROR)
            {
                if (rxMsgs[0].RxStatus == RxStatus.NONE)
                {
                    break;
                }
                msgs.Add(rxMsgs[0].GetBytes());
            }

            //If we couldn't find the start of the mesage give up
            if (J2534Status != J2534Err.STATUS_NOERROR)
            {
                throw new J2534Exception(J2534Status);
            }
            if (rxMsgs.Count < 1)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }

            UDSPacket rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.TRANSFER_DATA);
            var       b        = rxMsgs[0].GetBytes();

            msgs.Add(b);
            if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
            {
                while (rxPacket.NegativeResponse == UDScmd.NegativeResponse.REPONSE_PENDING)
                {
                    ReadMessage(out rxMsgs, 250);
                    if (J2534Status != J2534Err.STATUS_NOERROR)
                    {
                        throw new J2534Exception(J2534Status);
                    }
                    if (rxMsgs.Count < 1)
                    {
                        throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
                    }
                    rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.TRANSFER_DATA);
                    msgs.Add(rxMsgs[0].GetBytes());
                }

                //If we get a different negative response code then this is an actual error
                if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
                {
                    throw new UDSException(rxPacket.NegativeResponse);
                }
            }
        }
Beispiel #7
0
        //This is used to erase the flash
        public void EraseFlash(BackgroundWorker progressReporter = null)
        {
            //Non Standard Manafacturer Specific Mode EraseFlash (Ford Spanish Oak)
            //byte1 ServiceID 0xB1
            //byte2 AddressAndLengthFormatIdentifier (0x00 for Ford Spanish Oak)
            //byte3 0xB2 magic byte 1
            //byte4 0xAA
            byte[] txMsgBytes = { (byte)UDScmd.Mode.DIAGNOSTIC_COMMAND, 0x00, 0xB2, 0xAA };
            SendMessage(txMsgBytes);

            List <PassThruMsg> rxMsgs;

            while (ReadMessage(out rxMsgs, 250) == J2534Err.STATUS_NOERROR)
            {
                if (rxMsgs[0].RxStatus == RxStatus.NONE)
                {
                    break;
                }
            }

            //Expect back 0x7F B1 78  (78=Response Pending)
            //0xF1 00 B2  which is success

            //If we couldn't find the start of the mesage give up
            if (J2534Status != J2534Err.STATUS_NOERROR)
            {
                throw new J2534Exception(J2534Status);
            }
            if (rxMsgs.Count < 1)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }

            UDSPacket rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.DIAGNOSTIC_COMMAND);

            if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
            {
                //We expect a negative response but with response pending
                if (rxPacket.NegativeResponse != UDScmd.NegativeResponse.REPONSE_PENDING)
                {
                    throw new UDSException(rxPacket.NegativeResponse);
                }

                //Wait for the PCM to erase the flash
                ReadMessage(out rxMsgs, 15000);

                //If we couldn't find the start of the mesage give up
                if (J2534Status != J2534Err.STATUS_NOERROR)
                {
                    throw new J2534Exception(J2534Status);
                }
                if (rxMsgs.Count < 1)
                {
                    throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
                }

                rxPacket = ParseUDSResponse(rxMsgs[0], UDScmd.Mode.DIAGNOSTIC_COMMAND);
                if (rxPacket.Response != UDScmd.Response.POSTIVE_RESPONSE)
                {
                    throw new UDSException(rxPacket.NegativeResponse);
                }
            }

            if (rxPacket.Payload.Length < 2)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }

            //There is no IS14229 spec for this command so we manually check it
            if (rxPacket.Payload[0] != 0x00 || rxPacket.Payload[1] != 0xB2)
            {
                throw new J2534Exception(J2534Err.ERR_INVALID_MSG);
            }
        }