1 | /* |
2 | * Copyright (c) 2007-2015 Freescale Semiconductor, Inc. |
3 | * Copyright 2018-2021 NXP |
4 | * |
5 | * License: NXP LA_OPT_NXP_Software_License |
6 | * |
7 | * NXP Confidential. This software is owned or controlled by NXP and may |
8 | * only be used strictly in accordance with the applicable license terms. |
9 | * By expressly accepting such terms or by downloading, installing, |
10 | * activating and/or otherwise using the software, you are agreeing that |
11 | * you have read, and that you agree to comply with and are bound by, |
12 | * such license terms. If you do not agree to be bound by the applicable |
13 | * license terms, then you may not retain, install, activate or otherwise |
14 | * use the software. This code may only be used in a microprocessor, |
15 | * microcontroller, sensor or digital signal processor ("NXP Product") |
16 | * supplied directly or indirectly from NXP. See the full NXP Software |
17 | * License Agreement in license/LA_OPT_NXP_Software_License.pdf |
18 | * |
19 | * FreeMASTER Communication Driver - protocol implementation |
20 | */ |
21 | |
22 | #include "freemaster.h" |
23 | #include "freemaster_private.h" |
24 | #include "freemaster_protocol.h" |
25 | #include "freemaster_utils.h" |
26 | |
27 | #if FMSTR_DISABLE == 0 |
28 | |
29 | /* When using sessions, calculate number of instances of each lockable feature as U8 type */ |
30 | #if FMSTR_SESSION_COUNT > 1 |
31 | |
32 | #if FMSTR_USE_SCOPE > 0 |
33 | #define _FMSTR_SC ((FMSTR_U8)(FMSTR_USE_SCOPE)) |
34 | #else |
35 | #define _FMSTR_SC 0U |
36 | #endif |
37 | |
38 | #if FMSTR_USE_RECORDER > 0 |
39 | #define _FMSTR_RC ((FMSTR_U8)(FMSTR_USE_RECORDER)) |
40 | #else |
41 | #define _FMSTR_RC 0U |
42 | #endif |
43 | |
44 | #if FMSTR_USE_PIPES > 0 |
45 | #define _FMSTR_PC ((FMSTR_U8)(FMSTR_USE_PIPES)) |
46 | #else |
47 | #define _FMSTR_PC 0U |
48 | #endif |
49 | |
50 | #if FMSTR_USE_APPCMD > 0 |
51 | #define _FMSTR_AC 1U /* All app commands make up one instance, if enabled */ |
52 | #else |
53 | #define _FMSTR_AC 0U |
54 | #endif |
55 | |
56 | #define _FMSTR_FPG 1U /* Flash programmer is a lockable software feature. Always enabled */ |
57 | |
58 | /* Macros to convert instance to an index in one large fature locking array */ |
59 | |
60 | #define FMSTR_FEATURE_SCOPE_INSTANCE(n) ((FMSTR_U8)(n)) |
61 | #define FMSTR_FEATURE_REC_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + (FMSTR_U8)(n))) |
62 | #define FMSTR_FEATURE_APPCMD_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + 0U)) |
63 | #define FMSTR_FEATURE_FLASHPROG_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + _FMSTR_AC + 0U)) |
64 | #define FMSTR_FEATURE_PIPE_INSTANCE(n) ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + _FMSTR_AC + _FMSTR_FPG + (FMSTR_U8)(n))) |
65 | #define FMSTR_FEATURE_LOCK_COUNT ((FMSTR_U8)(_FMSTR_SC + _FMSTR_RC + _FMSTR_AC + _FMSTR_FPG + _FMSTR_PC)) |
66 | |
67 | typedef struct |
68 | { |
69 | FMSTR_SESSION *owner; /* Session which locks feature */ |
70 | FMSTR_S32 lockCount; /* Locked count */ |
71 | } FMSTR_FEATURE_LOCK; |
72 | #endif |
73 | |
74 | /****************************************************************************** |
75 | * Local Functions |
76 | ******************************************************************************/ |
77 | |
78 | /* The functions are local, but not declared "static" to prevent linker warnings |
79 | when features are excluded from protocol. */ |
80 | const FMSTR_CHAR *_FMSTR_GetAccessPassword(FMSTR_U8 requiredAccess); |
81 | FMSTR_BPTR _FMSTR_GetBoardConfig(FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
82 | FMSTR_BPTR _FMSTR_AuthenticationStep1(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
83 | FMSTR_BPTR _FMSTR_AuthenticationStep2(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
84 | FMSTR_BPTR _FMSTR_ReadMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
85 | FMSTR_BPTR _FMSTR_ReadMemBaseAddress(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
86 | FMSTR_BPTR _FMSTR_WriteMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
87 | |
88 | static FMSTR_SESSION *_FMSTR_FindSession(void *identification, FMSTR_BOOL create); |
89 | |
90 | #if FMSTR_SESSION_COUNT > 1 |
91 | static FMSTR_BPTR _FMSTR_FeatureLock(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus); |
92 | #endif |
93 | /****************************************************************************** |
94 | * Local variables |
95 | ******************************************************************************/ |
96 | |
97 | /* Protocol sessions */ |
98 | static FMSTR_SESSION fmstr_sessions[FMSTR_SESSION_COUNT]; |
99 | |
100 | #if FMSTR_SESSION_COUNT > 1 |
101 | /* Features */ |
102 | static FMSTR_FEATURE_LOCK fmstr_features[FMSTR_FEATURE_LOCK_COUNT]; |
103 | #endif |
104 | |
105 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
106 | /* To save stack usage, we have the following SHA context variables static, although |
107 | * they could be local in Auth2 function. */ |
108 | static FMSTR_SHA1_CTX fmstr_sha1Ctx; |
109 | /* Currently granted access (one of FMSTR_RESTRICTED_ACCESS_xxx). */ |
110 | static FMSTR_U8 fmstr_dfltGrantedAccess; |
111 | #endif /* FMSTR_CFG_F1_RESTRICTED_ACCESS */ |
112 | |
113 | #if FMSTR_DEBUG_TX > 0 |
114 | /* This warning is for you not to forget to disable the DEBUG_TX mode once the |
115 | * communication line works fine. You can ignore this warning if it is okay |
116 | * that the application will be periodically sending test frames to the world. */ |
117 | #warning FMSTR_DEBUG_TX is enabled. Test frames will be transmitted periodically. |
118 | /* When communication debugging mode is requested, this global variable is used to |
119 | turn the debugging off once a valid connection is detected */ |
120 | FMSTR_BOOL fmstr_doDebugTx; |
121 | #endif |
122 | |
123 | /****************************************************************************** |
124 | * |
125 | * @brief FreeMASTER driver initialization |
126 | * |
127 | ******************************************************************************/ |
128 | |
129 | FMSTR_BOOL FMSTR_Init(void) |
130 | { |
131 | FMSTR_BOOL ok = FMSTR_TRUE; |
132 | |
133 | FMSTR_MemSet(&fmstr_sessions, 0, sizeof(fmstr_sessions)); |
134 | |
135 | #if FMSTR_SESSION_COUNT > 1 |
136 | FMSTR_MemSet(&fmstr_features, 0, sizeof(fmstr_features)); |
137 | #endif |
138 | |
139 | #if FMSTR_DEBUG_LEVEL >= 1 |
140 | FMSTR_DEBUG_PRINTF("FMSTR Init begins\n"); |
141 | #endif |
142 | |
143 | /* Check the transport interface validity */ |
144 | FMSTR_ASSERT_RETURN(FMSTR_TRANSPORT.Init != NULL, FMSTR_FALSE); |
145 | FMSTR_ASSERT_RETURN(FMSTR_TRANSPORT.Poll != NULL, FMSTR_FALSE); |
146 | FMSTR_ASSERT_RETURN(FMSTR_TRANSPORT.SendResponse != NULL, FMSTR_FALSE); |
147 | |
148 | #if FMSTR_USE_TSA > 0 |
149 | /* initialize TSA */ |
150 | if (FMSTR_InitTsa() == FMSTR_FALSE) |
151 | { |
152 | ok = FMSTR_FALSE; |
153 | } |
154 | #endif |
155 | |
156 | #if FMSTR_USE_SCOPE > 0 |
157 | /* initialize Scope */ |
158 | if (FMSTR_InitScope() == FMSTR_FALSE) |
159 | { |
160 | ok = FMSTR_FALSE; |
161 | } |
162 | #endif |
163 | |
164 | #if FMSTR_USE_RECORDER > 0 |
165 | /* initialize Recorder */ |
166 | if (FMSTR_InitRec() == FMSTR_FALSE) |
167 | { |
168 | ok = FMSTR_FALSE; |
169 | } |
170 | #endif |
171 | |
172 | #if FMSTR_USE_APPCMD > 0 |
173 | /* initialize application commands */ |
174 | if (FMSTR_InitAppCmds() == FMSTR_FALSE) |
175 | { |
176 | ok = FMSTR_FALSE; |
177 | } |
178 | #endif |
179 | |
180 | #if FMSTR_USE_PIPES > 0 |
181 | /* initialize PIPES interface */ |
182 | if (FMSTR_InitPipes() == FMSTR_FALSE) |
183 | { |
184 | ok = FMSTR_FALSE; |
185 | } |
186 | #endif |
187 | |
188 | /* initialize communication layer and start listening for commands */ |
189 | if (FMSTR_TRANSPORT.Init() == FMSTR_FALSE) |
190 | { |
191 | ok = FMSTR_FALSE; |
192 | } |
193 | |
194 | #if FMSTR_DEBUG_TX > 0 |
195 | /* start in the debugging mode, we will be sending test frames periodically */ |
196 | fmstr_doDebugTx = FMSTR_TRUE; |
197 | #endif |
198 | |
199 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
200 | fmstr_dfltGrantedAccess = FMSTR_RESTRICTED_ACCESS_NO; |
201 | /* set the access level to the highest "open" level (the one without a password) */ |
202 | for (FMSTR_U8 access = FMSTR_RESTRICTED_ACCESS_R; access <= FMSTR_RESTRICTED_ACCESS_RWF; access++) |
203 | { |
204 | if (_FMSTR_GetAccessPassword(access) != NULL) |
205 | { |
206 | break; /* this level (and all levels above) are protected by a password */ |
207 | } |
208 | else |
209 | { |
210 | fmstr_dfltGrantedAccess = access; |
211 | } |
212 | } |
213 | #endif |
214 | |
215 | #if FMSTR_DEBUG_LEVEL >= 1 |
216 | FMSTR_DEBUG_PRINTF("FMSTR Init finished, ok=%d\n", (int)ok); |
217 | #endif |
218 | |
219 | return ok; |
220 | } |
221 | |
222 | /******************************************************************************* |
223 | * |
224 | * @brief API: Main "Polling" call from the application main loop |
225 | * |
226 | * This function either handles all the communication (polling-only mode = |
227 | * FMSTR_POLL_DRIVEN) or decodes messages received on the background by SCI interrupt |
228 | * (short-interrupt mode = FMSTR_SHORT_INTR). |
229 | * |
230 | * |
231 | *******************************************************************************/ |
232 | |
233 | void FMSTR_Poll(void) |
234 | { |
235 | /* Increase entropy in each poll round */ |
236 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
237 | static FMSTR_U8 e = 0x7U; |
238 | FMSTR_Randomize(e); |
239 | e += 13U; |
240 | #endif |
241 | |
242 | FMSTR_TRANSPORT.Poll(); |
243 | } |
244 | |
245 | /****************************************************************************** |
246 | * |
247 | * @brief Finalize transmit buffer before transmitting |
248 | * |
249 | * @param length - response length |
250 | * |
251 | * |
252 | * This Function takes the data already prepared in the transmit buffer |
253 | * (inlcuding the status byte). It computes the check sum and kicks on tx. |
254 | * |
255 | ******************************************************************************/ |
256 | |
257 | void FMSTR_SendResponse(FMSTR_BPTR response, FMSTR_SIZE length, FMSTR_U8 statusCode, FMSTR_SESSION *session) |
258 | { |
259 | /* Allow NULL session only if sessions count is 1, use the first (single) session as default. */ |
260 | if (session == NULL) |
261 | { |
262 | #if FMSTR_SESSION_COUNT == 1 |
263 | session = &fmstr_sessions[0]; |
264 | #else |
265 | /* You must specify session when multiple sessions are supported */ |
266 | FMSTR_ASSERT(FMSTR_FALSE); |
267 | return; |
268 | #endif |
269 | } |
270 | |
271 | #if FMSTR_DEBUG_LEVEL >= 2 |
272 | FMSTR_DEBUG_PRINTF("FMSTR SendResponse Status: 0x%x, Len: 0x%x\n", statusCode, length); |
273 | #endif |
274 | |
275 | FMSTR_TRANSPORT.SendResponse(response, length, statusCode, session->identification); |
276 | } |
277 | |
278 | /****************************************************************************** |
279 | * |
280 | * @brief Decodes the FreeMASTER protocol and calls appropriate handlers |
281 | * |
282 | * @param msgBuffIO - message in/out buffer |
283 | * @param identification - transport identification |
284 | * |
285 | * @return TRUE if frame was valid and any output was generated to IO buffer |
286 | * |
287 | * This Function decodes given message and invokes proper command handler |
288 | * which fills in the response. The response transmission is initiated |
289 | * in this call as well. |
290 | * |
291 | ******************************************************************************/ |
292 | |
293 | FMSTR_BOOL FMSTR_ProtocolDecoder(FMSTR_BPTR msgBuffIO, FMSTR_SIZE msgSize, FMSTR_U8 cmdCode, void *identification) |
294 | { |
295 | FMSTR_BPTR responseEnd = msgBuffIO; |
296 | FMSTR_U8 statusCode = FMSTR_STS_INVALID; |
297 | FMSTR_SESSION *activeSession = NULL; |
298 | |
299 | #if FMSTR_DEBUG_LEVEL >= 2 |
300 | FMSTR_DEBUG_PRINTF("FMSTR ProtocolDecoder Cmd: 0x%x, Len: 0x%x\n", cmdCode, msgSize); |
301 | #endif |
302 | |
303 | /* Find session (or free) and create it for this identification */ |
304 | activeSession = _FMSTR_FindSession(identification, FMSTR_TRUE); |
305 | |
306 | FMSTR_ASSERT_RETURN(activeSession != NULL, FMSTR_FALSE); |
307 | |
308 | /* process command */ |
309 | switch (cmdCode) |
310 | { |
311 | /* retrieve board configuration value*/ |
312 | case FMSTR_CMD_GETCONFIG: |
313 | responseEnd = _FMSTR_GetBoardConfig(msgBuffIO, &statusCode); |
314 | break; |
315 | |
316 | #if FMSTR_USE_READMEM > 0 |
317 | /* read a block of memory */ |
318 | case FMSTR_CMD_READMEM: |
319 | responseEnd = _FMSTR_ReadMem(activeSession, msgBuffIO, &statusCode); |
320 | break; |
321 | |
322 | #ifdef FMSTR_PLATFORM_BASE_ADDRESS |
323 | /* read a block of memory with base address*/ |
324 | case FMSTR_CMD_READMEM_BA: |
325 | responseEnd = _FMSTR_ReadMemBaseAddress(activeSession, msgBuffIO, &statusCode); |
326 | break; |
327 | #endif |
328 | |
329 | #endif /* FMSTR_USE_READMEM */ |
330 | |
331 | #if FMSTR_USE_WRITEMEM > 0 |
332 | /* write a block of memory */ |
333 | case FMSTR_CMD_WRITEMEM: |
334 | responseEnd = _FMSTR_WriteMem(activeSession, msgBuffIO, &statusCode); |
335 | break; |
336 | #endif /* FMSTR_USE_WRITEMEM */ |
337 | |
338 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
339 | /* Initiate password authentication, request authentication challenge */ |
340 | case FMSTR_CMD_AUTH1: |
341 | responseEnd = _FMSTR_AuthenticationStep1(activeSession, msgBuffIO, &statusCode); |
342 | break; |
343 | |
344 | /* Initiate password authentication, request authentication challenge */ |
345 | case FMSTR_CMD_AUTH2: |
346 | responseEnd = _FMSTR_AuthenticationStep2(activeSession, msgBuffIO, &statusCode); |
347 | break; |
348 | #endif |
349 | |
350 | #if FMSTR_USE_PIPES > 0 |
351 | case FMSTR_CMD_GETPIPE: |
352 | responseEnd = FMSTR_GetPipe(activeSession, msgBuffIO, msgSize, &statusCode); |
353 | break; |
354 | case FMSTR_CMD_PIPE: |
355 | responseEnd = FMSTR_PipeFrame(activeSession, msgBuffIO, msgSize, &statusCode); |
356 | break; |
357 | #endif /* FMSTR_USE_PIPES */ |
358 | |
359 | #if FMSTR_USE_TSA > 0 |
360 | /* get TSA table (force EX instead of non-EX) */ |
361 | case FMSTR_CMD_GETTSAINFO: |
362 | responseEnd = FMSTR_GetTsaInfo(msgBuffIO, &statusCode); |
363 | break; |
364 | |
365 | case FMSTR_CMD_GETSTRLEN: |
366 | responseEnd = FMSTR_GetStringLen(msgBuffIO, &statusCode); |
367 | break; |
368 | |
369 | case FMSTR_CMD_URESRWI: |
370 | responseEnd = FMSTR_UresControl(msgBuffIO, msgSize, &statusCode); |
371 | break; |
372 | #endif /* FMSTR_USE_TSA */ |
373 | |
374 | #if FMSTR_USE_APPCMD > 0 |
375 | /* accept the application command */ |
376 | case FMSTR_CMD_SENDAPPCMD: |
377 | responseEnd = FMSTR_StoreAppCmd(activeSession, msgBuffIO, msgSize, &statusCode); |
378 | break; |
379 | |
380 | /* get the application command status */ |
381 | case FMSTR_CMD_GETAPPCMDSTS: |
382 | responseEnd = FMSTR_GetAppCmdStatus(activeSession, msgBuffIO, &statusCode); |
383 | break; |
384 | |
385 | /* get the application command data */ |
386 | case FMSTR_CMD_GETAPPCMDDATA: |
387 | responseEnd = FMSTR_GetAppCmdRespData(activeSession, msgBuffIO, &statusCode); |
388 | break; |
389 | #endif /* FMSTR_USE_APPCMD */ |
390 | |
391 | #if FMSTR_USE_RECORDER > 0 |
392 | /* get recorder data */ |
393 | case FMSTR_CMD_GETREC: |
394 | responseEnd = FMSTR_GetRecCmd(activeSession, msgBuffIO, &statusCode); |
395 | break; |
396 | |
397 | /* setup recorder */ |
398 | case FMSTR_CMD_SETREC: |
399 | responseEnd = FMSTR_SetRecCmd(activeSession, msgBuffIO, msgSize, &statusCode); |
400 | break; |
401 | #endif /* FMSTR_USE_RECORDER */ |
402 | |
403 | #if FMSTR_USE_SCOPE > 0 |
404 | /* prepare scope variables */ |
405 | case FMSTR_CMD_SETSCOPE: |
406 | responseEnd = FMSTR_SetScope(activeSession, msgBuffIO, msgSize, &statusCode); |
407 | break; |
408 | |
409 | case FMSTR_CMD_READSCOPE: |
410 | responseEnd = FMSTR_ReadScope(activeSession, msgBuffIO, &statusCode, FMSTR_COMM_BUFFER_SIZE); |
411 | break; |
412 | #endif /* FMSTR_USE_SCOPE */ |
413 | |
414 | #if FMSTR_SESSION_COUNT > 1 |
415 | /* Lock or unlock feature in a multi-session configuration */ |
416 | case FMSTR_CMD_FEATLOCK: |
417 | responseEnd = _FMSTR_FeatureLock(activeSession, msgBuffIO, &statusCode); |
418 | break; |
419 | #endif /* FMSTR_SESSION_COUNT > 1 */ |
420 | |
421 | /* unknown command */ |
422 | default: |
423 | statusCode = FMSTR_STC_INVCMD; |
424 | break; |
425 | } |
426 | |
427 | /* anything to send back? */ |
428 | if (statusCode != FMSTR_STS_INVALID) |
429 | { |
430 | /*lint -e{946,960} subtracting pointers is appropriate here */ |
431 | FMSTR_INDEX ptrDiff = (FMSTR_INDEX)(responseEnd - msgBuffIO); |
432 | FMSTR_SIZE respSize = (FMSTR_SIZE)ptrDiff; |
433 | |
434 | /* Non-variable length error responses are forced to 0 length */ |
435 | if ((statusCode & (FMSTR_STSF_VARLEN | FMSTR_STSF_ERROR)) == FMSTR_STSF_ERROR) |
436 | { |
437 | respSize = 0; |
438 | } |
439 | |
440 | #if FMSTR_DEBUG_TX > 0 |
441 | /* the first sane frame received from PC Host ends test frame sending */ |
442 | fmstr_doDebugTx = FMSTR_FALSE; |
443 | #endif |
444 | FMSTR_SendResponse(msgBuffIO, respSize, statusCode, activeSession); |
445 | return FMSTR_TRUE; |
446 | } |
447 | else |
448 | { |
449 | /* nothing sent out */ |
450 | return FMSTR_FALSE; |
451 | } |
452 | } |
453 | |
454 | /****************************************************************************** |
455 | * |
456 | * @brief Sending debug test frame |
457 | * |
458 | * @param msgBuffIO - outut frame buffer |
459 | * @param session - transport session |
460 | * |
461 | * @return True if successful (always in current implementation) |
462 | * |
463 | ******************************************************************************/ |
464 | |
465 | FMSTR_BOOL FMSTR_SendTestFrame(FMSTR_BPTR msgBuffIO, FMSTR_SESSION *session) |
466 | { |
467 | FMSTR_SendResponse(msgBuffIO, 0, FMSTR_STC_DEBUGTX_TEST, session); |
468 | return FMSTR_TRUE; |
469 | } |
470 | |
471 | /****************************************************************************** |
472 | * |
473 | * @brief Handling GETINFO or GETINFO_BRIEF |
474 | * |
475 | * @param msgBuffIO - original command (in) and response buffer (out) |
476 | * @param retStatus - response status |
477 | * |
478 | * @return As all command handlers, the return value should be the buffer |
479 | * pointer where the response data payload is finished |
480 | * |
481 | ******************************************************************************/ |
482 | |
483 | FMSTR_BPTR _FMSTR_GetBoardConfig(FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
484 | { |
485 | static const FMSTR_CHAR *const fmstr_cfgParamNames[] = { |
486 | "MTU", "VS", "NM", "DS", "BD", "F1", "BA", "RC", "SC", "PV", "PC", |
487 | }; |
488 | |
489 | FMSTR_BPTR response = msgBuffIO; |
490 | FMSTR_U8 respCode = FMSTR_STS_INVALID; |
491 | FMSTR_CHAR str[4]; |
492 | FMSTR_INDEX ix = 0; |
493 | |
494 | /* Get the IX from incomming buffer */ |
495 | msgBuffIO = FMSTR_IndexFromBuffer(&ix, msgBuffIO); |
496 | |
497 | if (ix == 0) |
498 | { |
499 | FMSTR_INDEX i; |
500 | /* Get the configuration name from incomming buffer */ |
501 | msgBuffIO = FMSTR_StringFromBuffer(msgBuffIO, str, sizeof(str)); |
502 | |
503 | /* Try to find the Index of the config item */ |
504 | for (i = 0; i < (FMSTR_INDEX)FMSTR_COUNTOF(fmstr_cfgParamNames); i++) |
505 | { |
506 | if (FMSTR_StrCmp(fmstr_cfgParamNames[i], str) == 0) |
507 | { |
508 | ix = i + 1; |
509 | break; |
510 | } |
511 | } |
512 | |
513 | if (ix == 0) |
514 | { |
515 | respCode = FMSTR_STC_EACCESS; |
516 | goto FMSTR_GetConfig_exit; |
517 | } |
518 | } |
519 | |
520 | respCode = FMSTR_STS_OK | FMSTR_STSF_VARLEN; |
521 | response = FMSTR_StringCopyToBuffer(response, fmstr_cfgParamNames[ix - 1]); |
522 | |
523 | /* The ix must corresponded to table fmstr_cfgParamNames incremented by one */ |
524 | switch (ix) |
525 | { |
526 | case 1: /* MTU */ |
527 | response = FMSTR_SizeToBuffer(response, FMSTR_COMM_BUFFER_SIZE); |
528 | break; |
529 | case 2: /* VS */ |
530 | response = FMSTR_StringCopyToBuffer(response, FMSTR_VERSION_STR); |
531 | break; |
532 | case 3: /* NM */ |
533 | response = FMSTR_StringCopyToBuffer(response, FMSTR_APPLICATION_STR); |
534 | break; |
535 | case 4: /* DS */ |
536 | response = FMSTR_StringCopyToBuffer(response, FMSTR_DESCRIPTION_STR); |
537 | break; |
538 | case 5: /* BD */ |
539 | response = FMSTR_StringCopyToBuffer(response, FMSTR_BUILDTIME_STR); |
540 | break; |
541 | case 6: /* F1 */ |
542 | response = FMSTR_ValueToBuffer8(response, FMSTR_CFG_F1); |
543 | break; |
544 | #ifdef FMSTR_PLATFORM_BASE_ADDRESS |
545 | case 7: /* BA */ |
546 | response = FMSTR_SizeToBuffer(response, FMSTR_PLATFORM_BASE_ADDRESS); |
547 | break; |
548 | #endif |
549 | case 8: /* RC */ |
550 | response = FMSTR_ValueToBuffer8(response, FMSTR_USE_RECORDER); |
551 | break; |
552 | case 9: /* SC */ |
553 | response = FMSTR_ValueToBuffer8(response, FMSTR_USE_SCOPE); |
554 | break; |
555 | case 10: /* PV */ |
556 | response = FMSTR_ValueToBuffer8(response, FMSTR_PRCTL_VER); |
557 | break; |
558 | case 11: /* PC */ |
559 | response = FMSTR_ValueToBuffer8(response, FMSTR_USE_PIPES); |
560 | break; |
561 | default: |
562 | respCode = FMSTR_STC_EACCESS; |
563 | break; |
564 | } |
565 | |
566 | FMSTR_GetConfig_exit: |
567 | *retStatus = respCode; |
568 | |
569 | return response; |
570 | } |
571 | |
572 | /* Helper call to obtain password required for certain access level. */ |
573 | |
574 | const FMSTR_CHAR *_FMSTR_GetAccessPassword(FMSTR_U8 requiredAccess) |
575 | { |
576 | const FMSTR_CHAR *password = NULL; |
577 | |
578 | #if defined(FMSTR_RESTRICTED_ACCESS_R_PASSWORD) |
579 | if (requiredAccess >= FMSTR_RESTRICTED_ACCESS_R) |
580 | { |
581 | password = (FMSTR_CHAR *)FMSTR_RESTRICTED_ACCESS_R_PASSWORD; |
582 | } |
583 | #endif |
584 | |
585 | #if defined(FMSTR_RESTRICTED_ACCESS_RW_PASSWORD) |
586 | if (requiredAccess >= FMSTR_RESTRICTED_ACCESS_RW) |
587 | { |
588 | password = (FMSTR_CHAR *)FMSTR_RESTRICTED_ACCESS_RW_PASSWORD; |
589 | } |
590 | #endif |
591 | |
592 | #if defined(FMSTR_RESTRICTED_ACCESS_RWF_PASSWORD) |
593 | if (requiredAccess >= FMSTR_RESTRICTED_ACCESS_RWF) |
594 | { |
595 | password = (FMSTR_CHAR *)FMSTR_RESTRICTED_ACCESS_RWF_PASSWORD; |
596 | } |
597 | #endif |
598 | |
599 | /* password remains NULL if requested level and any lower level are unprotected */ |
600 | return password; |
601 | } |
602 | |
603 | /****************************************************************************** |
604 | * |
605 | * @brief Handling FMSTR_CMD_AUTH1 command |
606 | * |
607 | * @param session - transport session |
608 | * @param msgBuffIO - original command (in) and response buffer (out) |
609 | * @param retStatus - response status |
610 | * |
611 | * @return As all command handlers, the return value should be the buffer |
612 | * pointer where the response data payload is finished |
613 | * |
614 | ******************************************************************************/ |
615 | |
616 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
617 | |
618 | FMSTR_BPTR _FMSTR_AuthenticationStep1(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
619 | { |
620 | FMSTR_BPTR response = msgBuffIO; |
621 | FMSTR_U8 reqAccess = 0; |
622 | |
623 | FMSTR_ASSERT(session != NULL); |
624 | |
625 | /* Get the Required access from incomming buffer */ |
626 | msgBuffIO = FMSTR_ValueFromBuffer8(&reqAccess, msgBuffIO); |
627 | |
628 | /* success */ |
629 | *retStatus = FMSTR_STS_OK | FMSTR_STSF_VARLEN; |
630 | |
631 | /* Check if password is needed for requested access. When logging-out, the client sends 0 as requested level. */ |
632 | if (reqAccess == 0U || _FMSTR_GetAccessPassword(reqAccess) == NULL) |
633 | { |
634 | /* no password is required, access is granted, we do not require the step 2 */ |
635 | session->restr.grantedAccess = reqAccess; |
636 | |
637 | FMSTR_FreeSession(session); |
638 | |
639 | return FMSTR_ValueToBuffer8(response, 0U); |
640 | } |
641 | |
642 | /* ULEB-encoded algorithm ID */ |
643 | response = FMSTR_SizeToBuffer(response, FMSTR_AUTHENT_PRTCL_SHA1); |
644 | |
645 | /* Generate random salt and store it to local buffer for later use with FMSTR_AuthenticationM2 handler. */ |
646 | (void)FMSTR_RandomNumbersToBuffer(session->restr.authSalt, sizeof(session->restr.authSalt)); |
647 | return FMSTR_CopyToBuffer(response, session->restr.authSalt, sizeof(session->restr.authSalt)); |
648 | } |
649 | |
650 | #endif /* FMSTR_CFG_F1_RESTRICTED_ACCESS */ |
651 | |
652 | /****************************************************************************** |
653 | * |
654 | * @brief Handling FMSTR_CMD_AUTH2 command |
655 | * |
656 | * @param session - transport session |
657 | * @param msgBuffIO - original command (in) and response buffer (out) |
658 | * @param retStatus - response status |
659 | * |
660 | * @return As all command handlers, the return value should be the buffer |
661 | * pointer where the response data payload is finished |
662 | * |
663 | ******************************************************************************/ |
664 | |
665 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
666 | |
667 | FMSTR_BPTR _FMSTR_AuthenticationStep2(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
668 | { |
669 | FMSTR_BPTR response = msgBuffIO; |
670 | FMSTR_U8 reqAccess = 0; |
671 | FMSTR_U8 access; |
672 | const FMSTR_CHAR *pass; |
673 | |
674 | /* Get the Required access from incomming buffer */ |
675 | msgBuffIO = FMSTR_ValueFromBuffer8(&reqAccess, msgBuffIO); |
676 | |
677 | /* Get access key provided by client */ |
678 | msgBuffIO = FMSTR_CopyFromBuffer(session->restr.accessKey, msgBuffIO, sizeof(session->restr.accessKey)); |
679 | FMSTR_UNUSED(msgBuffIO); |
680 | |
681 | /* Evaluate all levels (from 3..1) */ |
682 | for (access = FMSTR_RESTRICTED_ACCESS_RWF; access >= FMSTR_RESTRICTED_ACCESS_R; access--) |
683 | { |
684 | if ((pass = _FMSTR_GetAccessPassword(access)) == NULL) |
685 | { |
686 | break; /* this access level and all lower levels are open (can be granted) */ |
687 | } |
688 | |
689 | #if FMSTR_USE_HASHED_PASSWORDS > 0 |
690 | /* Password is already hashed */ |
691 | FMSTR_MemCpyFrom(fmstr_localKey, (FMSTR_ADDR)pass, sizeof(fmstr_localKey)); |
692 | #else |
693 | /* Password was provided as a string, compute SHA1 hash now */ |
694 | FMSTR_MemSet(session->restr.localKey, 0, sizeof(session->restr.localKey)); |
695 | FMSTR_Sha1Init(&fmstr_sha1Ctx); |
696 | FMSTR_Sha1Update(&fmstr_sha1Ctx, (const FMSTR_U8 *)pass, FMSTR_StrLen(pass)); |
697 | FMSTR_Sha1Final(&fmstr_sha1Ctx, session->restr.localKey); |
698 | #endif |
699 | |
700 | /* compute correct key as SHA1(salt + SHA1(password) + salt) */ |
701 | FMSTR_Sha1Init(&fmstr_sha1Ctx); |
702 | FMSTR_Sha1Update(&fmstr_sha1Ctx, session->restr.authSalt, sizeof(session->restr.authSalt)); |
703 | FMSTR_Sha1Update(&fmstr_sha1Ctx, session->restr.localKey, sizeof(session->restr.localKey)); |
704 | FMSTR_Sha1Update(&fmstr_sha1Ctx, session->restr.authSalt, sizeof(session->restr.authSalt)); |
705 | FMSTR_Sha1Final(&fmstr_sha1Ctx, session->restr.localKey); |
706 | |
707 | /* is access key valid? (i.e. is client's password valid?) */ |
708 | if (FMSTR_MemCmp(session->restr.localKey, session->restr.accessKey, sizeof(session->restr.localKey)) == 0) |
709 | { |
710 | break; |
711 | } |
712 | } |
713 | |
714 | /* Here, the access is the maximum level which is possible to grant with the password provided */ |
715 | |
716 | /* Do not grant higher level than requested */ |
717 | session->restr.grantedAccess = access <= reqAccess ? access : reqAccess; |
718 | |
719 | /* Return success if at least some access level has been granted. Or when user was only validating the password with |
720 | * level=0. */ |
721 | if (access != 0U || reqAccess == 0U) |
722 | { |
723 | *retStatus = FMSTR_STS_OK; |
724 | response = FMSTR_ValueToBuffer8(response, session->restr.grantedAccess); |
725 | } |
726 | else |
727 | { |
728 | *retStatus = FMSTR_STC_EPASS; |
729 | } |
730 | |
731 | return response; |
732 | } |
733 | |
734 | #endif /* FMSTR_CFG_F1_RESTRICTED_ACCESS */ |
735 | |
736 | /****************************************************************************** |
737 | * |
738 | * @brief Handling READMEM command |
739 | * |
740 | * @param session - transport session |
741 | * @param msgBuffIO - original command (in) and response buffer (out) |
742 | * @param retStatus - response status |
743 | * |
744 | * @return As all command handlers, the return value should be the buffer |
745 | * pointer where the response data payload is finished |
746 | * |
747 | ******************************************************************************/ |
748 | |
749 | FMSTR_BPTR _FMSTR_ReadMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
750 | { |
751 | FMSTR_BPTR response = msgBuffIO; |
752 | FMSTR_ADDR addr; |
753 | FMSTR_SIZE size; |
754 | |
755 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
756 | if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_R) |
757 | { |
758 | *retStatus = FMSTR_STC_EAUTH; |
759 | return response; |
760 | } |
761 | #endif |
762 | |
763 | /* Get the Address from incomming buffer */ |
764 | msgBuffIO = FMSTR_AddressFromBuffer(&addr, msgBuffIO); |
765 | /* Get the Size from incomming buffer */ |
766 | msgBuffIO = FMSTR_SizeFromBuffer(&size, msgBuffIO); |
767 | |
768 | #if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY |
769 | if (FMSTR_CheckTsaSpace(addr, size, FMSTR_FALSE) == FMSTR_FALSE) |
770 | { |
771 | *retStatus = FMSTR_STC_EACCESS; |
772 | return response; |
773 | } |
774 | #endif |
775 | |
776 | /* check the response will safely fit into comm buffer */ |
777 | if (size > (FMSTR_U16)FMSTR_COMM_BUFFER_SIZE) |
778 | { |
779 | *retStatus = FMSTR_STC_RSPBUFFOVF; |
780 | return response; |
781 | } |
782 | |
783 | /* success */ |
784 | *retStatus = FMSTR_STS_OK; |
785 | return FMSTR_CopyToBuffer(response, addr, size); |
786 | } |
787 | |
788 | /****************************************************************************** |
789 | * |
790 | * @brief Handling READMEM command with base address |
791 | * |
792 | * @param session - transport session |
793 | * @param msgBuffIO - original command (in) and response buffer (out) |
794 | * @param retStatus - response status |
795 | * |
796 | * @return As all command handlers, the return value should be the buffer |
797 | * pointer where the response data payload is finished |
798 | * |
799 | ******************************************************************************/ |
800 | |
801 | #ifdef FMSTR_PLATFORM_BASE_ADDRESS |
802 | |
803 | FMSTR_BPTR _FMSTR_ReadMemBaseAddress(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
804 | { |
805 | FMSTR_BPTR response = msgBuffIO; |
806 | FMSTR_ADDR addr; |
807 | FMSTR_SIZE size; |
808 | FMSTR_INDEX index; |
809 | |
810 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
811 | if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_R) |
812 | { |
813 | *retStatus = FMSTR_STC_EAUTH; |
814 | return response; |
815 | } |
816 | #endif |
817 | |
818 | /* Get the Relative address to base from incoming buffer */ |
819 | msgBuffIO = FMSTR_IndexFromBuffer(&index, msgBuffIO); |
820 | /* Get the Size from incomming buffer */ |
821 | msgBuffIO = FMSTR_SizeFromBuffer(&size, msgBuffIO); |
822 | |
823 | addr = (FMSTR_ADDR)(FMSTR_PLATFORM_BASE_ADDRESS + index); |
824 | |
825 | #if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY |
826 | if (FMSTR_CheckTsaSpace(addr, size, FMSTR_FALSE) == FMSTR_FALSE) |
827 | { |
828 | *retStatus = FMSTR_STC_EACCESS; |
829 | return response; |
830 | } |
831 | #endif |
832 | |
833 | /* check the response will safely fit into comm buffer */ |
834 | if (size > (FMSTR_U16)FMSTR_COMM_BUFFER_SIZE) |
835 | { |
836 | *retStatus = FMSTR_STC_RSPBUFFOVF; |
837 | return response; |
838 | } |
839 | |
840 | /* success */ |
841 | *retStatus = FMSTR_STS_OK; |
842 | return FMSTR_CopyToBuffer(response, addr, size); |
843 | } |
844 | #endif /* FMSTR_PLATFORM_BASE_ADDRESS */ |
845 | |
846 | /****************************************************************************** |
847 | * |
848 | * @brief Handling WRITEMEM and WRITEMEM_EX commands |
849 | * |
850 | * @param session - transport session |
851 | * @param msgBuffIO - original command (in) and response buffer (out) |
852 | * @param retStatus - response status |
853 | * |
854 | * @return As all command handlers, the return value should be the buffer |
855 | * pointer where the response data payload is finished |
856 | * |
857 | ******************************************************************************/ |
858 | |
859 | FMSTR_BPTR _FMSTR_WriteMem(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
860 | { |
861 | FMSTR_BPTR response = msgBuffIO; |
862 | FMSTR_ADDR addr; |
863 | FMSTR_SIZE size; |
864 | FMSTR_U8 respCode, flags; |
865 | |
866 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
867 | if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_RW) |
868 | { |
869 | *retStatus = FMSTR_STC_EAUTH; |
870 | return response; |
871 | } |
872 | #endif |
873 | |
874 | /* Get the Flags from incomming buffer */ |
875 | msgBuffIO = FMSTR_ValueFromBuffer8(&flags, msgBuffIO); |
876 | /* Get the Address from incomming buffer */ |
877 | msgBuffIO = FMSTR_AddressFromBuffer(&addr, msgBuffIO); |
878 | /* Get the Size from incomming buffer */ |
879 | msgBuffIO = FMSTR_SizeFromBuffer(&size, msgBuffIO); |
880 | |
881 | #if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY |
882 | if (FMSTR_CheckTsaSpace(addr, size, FMSTR_TRUE) == FMSTR_FALSE) |
883 | { |
884 | respCode = FMSTR_STC_EACCESS; |
885 | goto FMSTR_WriteMem_exit; |
886 | } |
887 | #endif |
888 | |
889 | // TODO Add flash write support FLAG FMSTR_WRMFLAG_WRFLASH |
890 | |
891 | /*lint -e{534} ignoring function return value */ |
892 | if ((flags & FMSTR_WRMFLAG_WITHMASK) != 0U) |
893 | { |
894 | FMSTR_CopyFromBufferWithMask(addr, msgBuffIO, size); |
895 | } |
896 | else |
897 | { |
898 | msgBuffIO = FMSTR_CopyFromBuffer(addr, msgBuffIO, size); |
899 | FMSTR_UNUSED(msgBuffIO); |
900 | } |
901 | |
902 | respCode = FMSTR_STS_OK; |
903 | |
904 | #if FMSTR_USE_TSA && FMSTR_USE_TSA_SAFETY |
905 | FMSTR_WriteMem_exit: |
906 | #endif |
907 | |
908 | *retStatus = respCode; |
909 | |
910 | return response; |
911 | } |
912 | |
913 | #if FMSTR_SESSION_COUNT > 1 |
914 | /****************************************************************************** |
915 | * |
916 | * @brief Get feature structure from the static array of features |
917 | * |
918 | * @param featureType - feature type |
919 | * @param instance - instance number of the selected feature |
920 | * |
921 | * @return Selected feature struct |
922 | * |
923 | ******************************************************************************/ |
924 | |
925 | static FMSTR_FEATURE_LOCK *_FMSTR_FeatureGet(FMSTR_U8 featureType, FMSTR_U8 instance) |
926 | { |
927 | FMSTR_INDEX index = -1; |
928 | |
929 | switch (featureType) |
930 | { |
931 | #if FMSTR_USE_SCOPE > 0 |
932 | case FMSTR_FEATURE_SCOPE: |
933 | if (instance < _FMSTR_SC) |
934 | { |
935 | index = (FMSTR_INDEX)FMSTR_FEATURE_SCOPE_INSTANCE(instance); |
936 | } |
937 | break; |
938 | #endif |
939 | |
940 | #if FMSTR_USE_RECORDER > 0 |
941 | case FMSTR_FEATURE_REC: |
942 | if (instance < _FMSTR_RC) |
943 | { |
944 | index = (FMSTR_INDEX)FMSTR_FEATURE_REC_INSTANCE(instance); |
945 | } |
946 | break; |
947 | #endif |
948 | |
949 | #if FMSTR_USE_APPCMD > 0 |
950 | case FMSTR_FEATURE_APPCMD: |
951 | if (instance < _FMSTR_AC) |
952 | { |
953 | index = (FMSTR_INDEX)FMSTR_FEATURE_APPCMD_INSTANCE(instance); |
954 | } |
955 | break; |
956 | #endif |
957 | |
958 | case FMSTR_FEATURE_FLASHPROG: |
959 | if (instance < _FMSTR_FPG) |
960 | { |
961 | index = (FMSTR_INDEX)FMSTR_FEATURE_FLASHPROG_INSTANCE(instance); |
962 | } |
963 | break; |
964 | |
965 | #if FMSTR_USE_PIPES > 0 |
966 | case FMSTR_FEATURE_PIPE: |
967 | { |
968 | FMSTR_INDEX pipeIndex = FMSTR_FindPipeIndex(instance); |
969 | if (pipeIndex < (FMSTR_INDEX)_FMSTR_PC) |
970 | { |
971 | index = (FMSTR_INDEX)FMSTR_FEATURE_PIPE_INSTANCE(pipeIndex); |
972 | } |
973 | } |
974 | break; |
975 | #endif |
976 | |
977 | default: |
978 | index = -1; |
979 | break; |
980 | } |
981 | |
982 | /* Check max size */ |
983 | if (index < 0 || index > (FMSTR_INDEX)FMSTR_FEATURE_LOCK_COUNT) |
984 | { |
985 | return NULL; |
986 | } |
987 | |
988 | return &fmstr_features[index]; |
989 | } |
990 | |
991 | /****************************************************************************** |
992 | * |
993 | * @brief Lock or unlock feature in a multi-session configuration |
994 | * |
995 | * @param session - transport session |
996 | * @param msgBuffIO - original command (in) and response buffer (out) |
997 | * @param retStatus - response status |
998 | * |
999 | * @return As all command handlers, the return value should be the buffer |
1000 | * pointer where the response data payload is finished |
1001 | * |
1002 | ******************************************************************************/ |
1003 | |
1004 | static FMSTR_BPTR _FMSTR_FeatureLock(FMSTR_SESSION *session, FMSTR_BPTR msgBuffIO, FMSTR_U8 *retStatus) |
1005 | { |
1006 | FMSTR_BPTR response = msgBuffIO; |
1007 | FMSTR_FEATURE_LOCK *feature = NULL; |
1008 | FMSTR_U8 featType = 0; |
1009 | FMSTR_U8 instance = 0; |
1010 | FMSTR_U8 lock = 0; |
1011 | |
1012 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
1013 | if (session->restr.grantedAccess < FMSTR_RESTRICTED_ACCESS_R) |
1014 | { |
1015 | *retStatus = FMSTR_STC_EAUTH; |
1016 | return response; |
1017 | } |
1018 | #endif |
1019 | |
1020 | /* Get the Feature Type from incomming buffer */ |
1021 | msgBuffIO = FMSTR_ValueFromBuffer8(&featType, msgBuffIO); |
1022 | /* Get the Instance from incomming buffer */ |
1023 | msgBuffIO = FMSTR_ValueFromBuffer8(&instance, msgBuffIO); |
1024 | /* Get the Lock/Unlock from incomming buffer */ |
1025 | msgBuffIO = FMSTR_ValueFromBuffer8(&lock, msgBuffIO); |
1026 | |
1027 | /* Get feature struct */ |
1028 | feature = _FMSTR_FeatureGet(featType, instance); |
1029 | if (feature == NULL) |
1030 | { |
1031 | /* Invalid instance */ |
1032 | *retStatus = FMSTR_STC_EINSTANCE; |
1033 | return response; |
1034 | } |
1035 | |
1036 | /* Check locked session */ |
1037 | if (feature->lockCount > 0 && feature->owner != session) |
1038 | { |
1039 | /* Feature is locked by another session */ |
1040 | *retStatus = FMSTR_STC_SERVBUSY; |
1041 | return response; |
1042 | } |
1043 | |
1044 | /* Lock */ |
1045 | if (lock != 0U) |
1046 | { |
1047 | feature->lockCount++; |
1048 | feature->owner = session; |
1049 | } |
1050 | /* Unlock */ |
1051 | else |
1052 | { |
1053 | if (feature->lockCount > 0) |
1054 | { |
1055 | feature->lockCount--; |
1056 | } |
1057 | if (feature->lockCount == 0) |
1058 | { |
1059 | feature->owner = NULL; |
1060 | } |
1061 | } |
1062 | |
1063 | *retStatus = FMSTR_STS_OK; |
1064 | |
1065 | return response; |
1066 | } |
1067 | |
1068 | /****************************************************************************** |
1069 | * |
1070 | * @brief Unlock all features, which is owned by session |
1071 | * |
1072 | * @param session - transport session |
1073 | * |
1074 | ******************************************************************************/ |
1075 | |
1076 | static void _FMSTR_UnlockFeatures(FMSTR_SESSION *session) |
1077 | { |
1078 | FMSTR_FEATURE_LOCK *feature = NULL; |
1079 | FMSTR_U8 i; |
1080 | |
1081 | for (i = 0; i < FMSTR_FEATURE_LOCK_COUNT; i++) |
1082 | { |
1083 | feature = &fmstr_features[i]; |
1084 | if (feature->owner == session) |
1085 | { |
1086 | feature->lockCount = 0; |
1087 | feature->owner = NULL; |
1088 | } |
1089 | } |
1090 | } |
1091 | |
1092 | /****************************************************************************** |
1093 | * |
1094 | * @brief Check if feature is locked for the owner (session) |
1095 | * |
1096 | * @param session - transport session |
1097 | * @param featureType - feature type |
1098 | * @param instance - instance number of the selected feature |
1099 | * |
1100 | * @return locked state |
1101 | * |
1102 | ******************************************************************************/ |
1103 | |
1104 | FMSTR_BOOL FMSTR_IsFeatureOwned(FMSTR_SESSION *session, FMSTR_U8 featureType, FMSTR_U8 instance) |
1105 | { |
1106 | FMSTR_FEATURE_LOCK *feature = NULL; |
1107 | |
1108 | /* Get feature struct */ |
1109 | feature = _FMSTR_FeatureGet(featureType, instance); |
1110 | if (feature == NULL) |
1111 | { |
1112 | return FMSTR_FALSE; |
1113 | } |
1114 | |
1115 | if (feature->owner == session && feature->lockCount > 0) |
1116 | { |
1117 | return FMSTR_TRUE; |
1118 | } |
1119 | |
1120 | return FMSTR_FALSE; |
1121 | } |
1122 | #endif /* FMSTR_SESSION_COUNT > 1 */ |
1123 | |
1124 | /****************************************************************************** |
1125 | * |
1126 | * @brief Free transport session |
1127 | * |
1128 | * @param identification - transport identification |
1129 | * |
1130 | ******************************************************************************/ |
1131 | |
1132 | void FMSTR_FreeSession(void *identification) |
1133 | { |
1134 | FMSTR_SESSION *ses = _FMSTR_FindSession(identification, FMSTR_FALSE); |
1135 | if (ses != NULL && ses->identification == identification) |
1136 | { |
1137 | #if FMSTR_SESSION_COUNT > 1 |
1138 | /* Unlock all features, which is owned by session */ |
1139 | _FMSTR_UnlockFeatures(ses); |
1140 | #endif |
1141 | |
1142 | FMSTR_MemSet(ses, 0, sizeof(FMSTR_SESSION)); |
1143 | } |
1144 | } |
1145 | |
1146 | /****************************************************************************** |
1147 | * |
1148 | * @brief Find transport session by transport identification |
1149 | * |
1150 | * @param identification - transport identification |
1151 | * @param create - when true, creates session with transport identification |
1152 | * |
1153 | * @return Found/created session. |
1154 | * |
1155 | ******************************************************************************/ |
1156 | |
1157 | static FMSTR_SESSION *_FMSTR_FindSession(void *identification, FMSTR_BOOL create) |
1158 | { |
1159 | FMSTR_SESSION *ses; |
1160 | FMSTR_SESSION *freeSession = NULL; |
1161 | FMSTR_INDEX i; |
1162 | |
1163 | for (i = 0; i < FMSTR_SESSION_COUNT; i++) |
1164 | { |
1165 | ses = &fmstr_sessions[i]; |
1166 | |
1167 | /* Find session by identification */ |
1168 | if (ses->identification == identification) |
1169 | { |
1170 | return ses; |
1171 | } |
1172 | |
1173 | /* Find free session */ |
1174 | if (freeSession == NULL && ses->identification == NULL) |
1175 | { |
1176 | freeSession = ses; |
1177 | } |
1178 | } |
1179 | |
1180 | /* Set identification to session */ |
1181 | if (freeSession != NULL && create != FMSTR_FALSE) |
1182 | { |
1183 | freeSession->identification = identification; |
1184 | |
1185 | #if FMSTR_CFG_F1_RESTRICTED_ACCESS != 0 |
1186 | /* Initialize the access protection variables */ |
1187 | FMSTR_MemSet(freeSession->restr.authSalt, 0xaa, sizeof(freeSession->restr.authSalt)); |
1188 | freeSession->restr.grantedAccess = fmstr_dfltGrantedAccess; |
1189 | #endif |
1190 | } |
1191 | |
1192 | return freeSession; |
1193 | } |
1194 | |
1195 | #else /* !FMSTR_DISABLE */ |
1196 | |
1197 | /****************************************************************************** |
1198 | * |
1199 | * @brief FreeMASTER driver initialization is disabled |
1200 | * |
1201 | ******************************************************************************/ |
1202 | |
1203 | FMSTR_BOOL FMSTR_Init(void) |
1204 | { |
1205 | return FMSTR_FALSE; |
1206 | } |
1207 | |
1208 | /******************************************************************************* |
1209 | * |
1210 | * @brief API: Main "Polling" call from the application main loop |
1211 | * |
1212 | *******************************************************************************/ |
1213 | |
1214 | void FMSTR_Poll(void) |
1215 | { |
1216 | } |
1217 | |
1218 | #endif /* !FMSTR_DISABLE */ |
1219 | |