/
MessageFactory.cs
executable file
·269 lines (236 loc) · 9.17 KB
/
MessageFactory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flash411
{
/// <summary>
/// This class is responsible for generating the messages that the app sends to the PCM.
/// </summary>
/// <remarks>
/// The messages generated by this class are byte-for-byte exactly what the PCM
/// receives, with the exception of the CRC byte at the end. CRC bytes must be
/// added by the currently-selected Device class if the actual device doesn't add
/// the CRC byte automatically.
///
/// Some devices will require these messages to be translated according to the specific
/// device's protocol - that too is the job of the currently-selected Device class.
/// </remarks>
class MessageFactory
{
/// <summary>
/// Create a request to read the given block of PCM memory.
/// </summary>
public Message CreateReadRequest(byte block)
{
byte[] bytes = new byte[] { 0x6C, DeviceId.Pcm, DeviceId.Tool, 0x3C, block };
return new Message(bytes);
}
/// <summary>
/// Create a request to read the PCM's operating system ID.
/// </summary>
/// <returns></returns>
public Message CreateOperatingSystemIdReadRequest()
{
return CreateReadRequest(BlockId.OperatingSystemID);
}
/// <summary>
/// Create a request to read the PCM's Calibration ID.
/// </summary>
/// <returns></returns>
public Message CreateCalibrationIdReadRequest()
{
return CreateReadRequest(BlockId.CalibrationID);
}
/// <summary>
/// Create a request to read the PCM's Hardware ID.
/// </summary>
/// <returns></returns>
public Message CreateHardwareIdReadRequest()
{
return CreateReadRequest(BlockId.HardwareID);
}
/// <summary>
/// Create a request to read the first segment of the PCM's VIN.
/// </summary>
public Message CreateVinRequest1()
{
return CreateReadRequest(BlockId.Vin1);
}
/// <summary>
/// Create a request to read the second segment of the PCM's VIN.
/// </summary>
public Message CreateVinRequest2()
{
return CreateReadRequest(BlockId.Vin2);
}
/// <summary>
/// Create a request to read the thid segment of the PCM's VIN.
/// </summary>
public Message CreateVinRequest3()
{
return CreateReadRequest(BlockId.Vin3);
}
/// <summary>
/// Create a request to read the first segment of the PCM's Serial Number.
/// </summary>
public Message CreateSerialRequest1()
{
return CreateReadRequest(BlockId.Serial1);
}
/// <summary>
/// Create a request to read the second segment of the PCM's Serial Number.
/// </summary>
public Message CreateSerialRequest2()
{
return CreateReadRequest(BlockId.Serial2);
}
/// <summary>
/// Create a request to read the thid segment of the PCM's Serial Number.
/// </summary>
public Message CreateSerialRequest3()
{
return CreateReadRequest(BlockId.Serial3);
}
/// <summary>
/// Create a request to read the Broad Cast Code (BCC).
/// </summary>
public Message CreateBCCRequest()
{
return CreateReadRequest(BlockId.BCC);
}
/// <summary>
/// Create a request to read the Broad Cast Code (MEC).
/// </summary>
public Message CreateMECRequest()
{
return CreateReadRequest(BlockId.MEC);
}
/// <summary>
/// Create a request to retrieve a 'seed' value from the PCM
/// </summary>
public Message CreateSeedRequest()
{
byte[] bytes = new byte[] { 0x6C, DeviceId.Pcm, DeviceId.Tool, 0x27, 0x01 };
return new Message(bytes);
}
/// <summary>
/// Create a request to send a 'key' value to the PCM
/// </summary>
public Message CreateUnlockRequest(UInt16 key)
{
byte keyHigh = (byte)((key & 0xFF00) >> 8);
byte keyLow = (byte)(key & 0xFF);
byte[] bytes = new byte[] { 0x6C, DeviceId.Pcm, DeviceId.Tool, 0x27, 0x02, keyHigh, keyLow };
return new Message(bytes);
}
/// <summary>
/// Create a block message from the supplied arguments.
/// </summary>
public Message CreateBlockMessage(byte[] payload, int offset, int length, int address, bool execute)
{
//if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();
byte[] buffer = new byte[10 + length + 2];
byte[] header = new byte[10];
byte submode = 0;
if (execute == true) submode = (byte)(1 << 7); // execute bit
byte size1 = unchecked((byte)(length >> 8));
byte size2 = unchecked((byte)(length & 0xFF));
byte addr1 = unchecked((byte)(address >> 16));
byte addr2 = unchecked((byte)(address >> 8));
byte addr3 = unchecked((byte)(address & 0xFF));
header[0] = 0x6D;
header[1] = DeviceId.Pcm;
header[2] = DeviceId.Tool;
header[3] = 0x36;
header[4] = submode;
header[5] = size1;
header[6] = size2;
header[7] = addr1;
header[8] = addr2;
header[9] = addr3;
Buffer.BlockCopy(header, 0, buffer, 0, header.Length);
Buffer.BlockCopy(payload, offset, buffer, header.Length, length);
return new Message(AddBlockChecksum(buffer));
}
/// <summary>
/// Write a 16 bit sum to the end of a block, returns a Message, as a byte array
/// </summary>
/// <remarks>
/// Overwrites the last 2 bytes at the end of the array with the sum
/// </remarks>
public byte[] AddBlockChecksum(byte[] block)
{
UInt16 sum = 0;
for (int i = 4; i < block.Length-2; i++) // skip prio, dest, src, mode
{
sum += block[i];
}
block[block.Length - 2] = unchecked((byte)(sum >> 8));
block[block.Length - 1] = unchecked((byte)(sum & 0xFF));
return block;
}
/// <summary>
/// Create a request for the PCM to test VPW speed switch to 4x is OK
/// </summary>
public Message CreateHighSpeedCheck()
{
return new Message(new byte[] { 0x6C, 0xFE, DeviceId.Tool, 0xA0 });
}
/// <summary>
/// PCM Response if a switch to VPW 4x is OK
/// </summary>
public Message CreateHighSpeedOKResponse()
{
return new Message(new byte[] { 0x6C, DeviceId.Tool, DeviceId.Broadcast, 0xE0 });
}
/// <summary>
/// Create a request for the PCM to switch to VPW 4x
/// </summary>
public Message CreateBeginHighSpeed()
{
return new Message(new byte[] { 0x6C, DeviceId.Broadcast, DeviceId.Tool, 0xA1 });
}
/// <summary>
/// Create a broadcast message announcing there is a test device connected to the vehicle
/// </summary>
public Message CreateTestDevicePresent()
{
byte[] bytes = new byte[] { 0x6C, DeviceId.Broadcast, DeviceId.Tool, 0x3F };
return new Message(bytes);
}
/// <summary>
/// Create a broadcast message telling the PCM to clear DTCs
/// </summary>
public Message CreateClearDTCs()
{
byte[] bytes = new byte[] { 0x68, 0x6A, DeviceId.Tool, 0x04 };
return new Message(bytes);
}
/// <summary>
/// A successfull response seen after the Clear DTCs message
/// </summary>
public Message CreateClearDTCsOK()
{
byte[] bytes = new byte[] { 0x48, 0x6B, DeviceId.Pcm, 0x44 };
return new Message(bytes);
}
/// <summary>
/// Create a broadcast message telling all devices to disable normal message transmission (disable chatter)
/// </summary>
public Message CreateDisableNormalMessageTransmition()
{
byte[] bytes = new byte[] { 0x6C, DeviceId.Broadcast, DeviceId.Tool, 0x28, 0x00 };
return new Message(bytes);
}
/// <summary>
/// Create a broadcast message telling all devices to disable normal message transmission (disable chatter)
/// </summary>
public Message CreateDisableNormalMessageTransmitionOK()
{
byte[] bytes = new byte[] { 0x6C, DeviceId.Tool, DeviceId.Pcm, 0x68, 0x00 };
return new Message(bytes);
}
}
}