Skip to content

Commit 7f5bfbb

Browse files
committed
[opt]:add hex and s19 built in uds service
1 parent 6d680b8 commit 7f5bfbb

File tree

6 files changed

+587
-16
lines changed

6 files changed

+587
-16
lines changed

resources/buildInScript/RequestDownloadHex/index.js

Lines changed: 170 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"service": {
3+
"name": "RequestDownloadHex",
4+
"fixedParam": true,
5+
"buildInScript": "index.js",
6+
"hasSubFunction": false,
7+
"desc": "Combines services 0x34, 0x36(N), and 0x37 into one group. Supports hex files with optional handling for multiple non-contiguous hex file blocks. The address corresponds to the hex file address.",
8+
"defaultParams": [
9+
{
10+
"param": {
11+
"id": "dataFormatIdentifier",
12+
"name": "dataFormatIdentifier",
13+
"bitLen": 8,
14+
"deletable": false,
15+
"editable": true,
16+
"type": "NUM",
17+
"phyValue": "00"
18+
}
19+
},
20+
{
21+
"param": {
22+
"id": "addressAndLengthFormatIdentifier",
23+
"name": "addressAndLengthFormatIdentifier",
24+
"bitLen": 8,
25+
"deletable": false,
26+
"editable": true,
27+
"type": "NUM",
28+
"phyValue": "0x44",
29+
"value": {
30+
"type":"Buffer",
31+
"data":[68]
32+
}
33+
}
34+
},
35+
{
36+
"param": {
37+
"id": "hexFile",
38+
"name": "hexFile",
39+
"bitLen": 0,
40+
"deletable": false,
41+
"editable": true,
42+
"type": "FILE",
43+
"phyValue": ""
44+
}
45+
}
46+
],
47+
"defaultRespParams": []
48+
}
49+
}
50+
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Import ECB library
2+
const ECB=require('../../lib/js')
3+
const fsP = require('fs/promises')
4+
5+
// Queued blocks parsed from the s19 file
6+
const pendingBlocks = [];
7+
// Global variables to track current block and max chunk size
8+
var currentBlock = void 0;
9+
var maxChunkSize;
10+
var testerName;
11+
var dataFormatIdentifierCache;
12+
var addressAndLengthFormatIdentifierCache;
13+
var jobInstance;
14+
15+
// Initialize utility functions
16+
Util.Init(() => {
17+
testerName = Util.getTesterName();
18+
19+
// Build RequestDownload (0x34) for the current block
20+
const buildRequestDownload = () => {
21+
if (!currentBlock) {
22+
throw new Error("currentBlock is undefined");
23+
}
24+
25+
const r34 = new ECB.DiagRequest(testerName, {
26+
id: "",
27+
name: "",
28+
serviceId: "0x34",
29+
params: [],
30+
respParams: []
31+
});
32+
33+
const prefixBuffer = Buffer.from([0x34, dataFormatIdentifierCache & 0xff, addressAndLengthFormatIdentifierCache & 0xff]);
34+
35+
// Create buffer for memory address based on format identifier
36+
const memoryAddressBuffer = Buffer.alloc(addressAndLengthFormatIdentifierCache & 0x0f);
37+
for (let i = 0; i < memoryAddressBuffer.length; i++) {
38+
memoryAddressBuffer[i] = currentBlock.addr >> (8 * (memoryAddressBuffer.length - 1 - i)) & 0xff;
39+
}
40+
41+
// Create buffer for memory size based on format identifier
42+
const memorySizeBuffer = Buffer.alloc((addressAndLengthFormatIdentifierCache & 0xf0) >> 4);
43+
for (let i = 0; i < memorySizeBuffer.length; i++) {
44+
memorySizeBuffer[i] = currentBlock.data.length >> (8 * (memorySizeBuffer.length - 1 - i)) & 0xff;
45+
}
46+
47+
// Set raw request data by concatenating buffers
48+
r34.diagSetRaw(Buffer.concat([prefixBuffer, memoryAddressBuffer, memorySizeBuffer]));
49+
50+
// Handle response from ECU
51+
r34.On("recv", (resp) => {
52+
const data = resp.diagGetRaw();
53+
const lengthFormatIdentifier = (data[1] & 0xf0) >> 4;
54+
55+
let maxNumberOfBlockLength = 0;
56+
// Calculate max block length from response
57+
for (let i = 0; i < lengthFormatIdentifier; i++) {
58+
maxNumberOfBlockLength += data[2 + i] * Math.pow(256, lengthFormatIdentifier - i - 1);
59+
}
60+
maxChunkSize = maxNumberOfBlockLength;
61+
});
62+
63+
return r34;
64+
};
65+
66+
// Register main RequestDownloadS19 function
67+
Util.Register(`${testerName}.RequestDownloadS19`, async function(dataFormatIdentifier, addressAndLengthFormatIdentifier, s19FilePath) {
68+
// reset state for each call
69+
pendingBlocks.length = 0;
70+
currentBlock = void 0;
71+
maxChunkSize = void 0;
72+
dataFormatIdentifierCache = dataFormatIdentifier;
73+
addressAndLengthFormatIdentifierCache = addressAndLengthFormatIdentifier;
74+
75+
// parse s19 file into discrete memory blocks
76+
const s19Text = await fsP.readFile(s19FilePath, 'utf8');
77+
const memMap = ECB.S19MemoryMap.fromS19(s19Text);
78+
for (const [addr, data] of memMap) {
79+
pendingBlocks.push({ addr, data });
80+
}
81+
82+
if (pendingBlocks.length === 0) {
83+
throw new Error("s19 file contains no data");
84+
}
85+
86+
// prepare first block
87+
currentBlock = pendingBlocks.shift();
88+
89+
const r34 = buildRequestDownload();
90+
91+
// Create temporary job for handling data transfer
92+
const job = new ECB.DiagJob(testerName, {
93+
id: "RequestDownloadS19_tmpJob",
94+
name: "RequestDownloadS19_tmpJob",
95+
serviceId: "Job",
96+
params: [],
97+
respParams: []
98+
});
99+
jobInstance = job;
100+
101+
return [r34, job];
102+
});
103+
104+
// Register temporary job handler for data transfer
105+
Util.Register(`${testerName}.RequestDownloadS19_tmpJob`, () => {
106+
// Validate chunk size
107+
if (maxChunkSize == void 0 || maxChunkSize <= 2) {
108+
throw new Error("maxNumberOfBlockLength is undefined or too small");
109+
}
110+
111+
if (currentBlock) {
112+
// Adjust chunk size for overhead
113+
let chunkSize = maxChunkSize - 2;
114+
if (chunkSize & 7) {
115+
chunkSize -= chunkSize & 7;
116+
}
117+
118+
// Split data into chunks
119+
const numChunks = Math.ceil(currentBlock.data.length / chunkSize);
120+
const list = [];
121+
122+
// Create transfer data requests (0x36) for each chunk
123+
for (let i = 0; i < numChunks; i++) {
124+
const start = i * chunkSize;
125+
const end = Math.min(start + chunkSize, currentBlock.data.length);
126+
const chunk = currentBlock.data.subarray(start, end);
127+
128+
const r36 = new ECB.DiagRequest(testerName, {
129+
id: "",
130+
name: "",
131+
serviceId: "0x36",
132+
params: [],
133+
respParams: []
134+
});
135+
136+
// Add block sequence counter
137+
const blockSequenceCounter = Buffer.alloc(1);
138+
blockSequenceCounter.writeUInt8((i + 1) & 0xff);
139+
r36.diagSetRaw(Buffer.concat([Buffer.from([0x36]), blockSequenceCounter, chunk]));
140+
list.push(r36);
141+
}
142+
143+
// Create transfer exit request (0x37)
144+
const r37 = new ECB.DiagRequest(testerName, {
145+
id: "",
146+
name: "",
147+
serviceId: "0x37",
148+
params: [],
149+
respParams: []
150+
});
151+
r37.diagSetRaw(Buffer.from([0x37]));
152+
list.push(r37);
153+
154+
// prepare next block if any
155+
currentBlock = void 0;
156+
maxChunkSize = void 0;
157+
if (pendingBlocks.length > 0) {
158+
currentBlock = pendingBlocks.shift();
159+
list.push(buildRequestDownload(), jobInstance);
160+
}
161+
162+
return list;
163+
} else {
164+
return [];
165+
}
166+
});
167+
});
168+
169+
/*! For license information please see uds.js.LICENSE.txt */
170+
//# sourceMappingURL=tester.js.map
171+

0 commit comments

Comments
 (0)