1 /*
2 * Percepio DFM v2.0.0
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * DFM Session
9 */
10
11 #include <dfm.h>
12
13 #if ((DFM_CFG_ENABLED) >= 1)
14
15 typedef struct DfmSessionStorage
16 {
17 uint32_t ulVersion;
18 uint32_t ulEnabled;
19 } DfmSessionStorage_t;
20
21 #define DFM_SESSION_STORAGE_VERSION 1
22
23 #define DFM_SESSION_STORAGE_DUMMY_VALUE 0x93105271UL
24
25 #if ((DFM_DEVICE_NAME_MAX_LEN) < 8)
26 #error Minimum DFM_CFG_DEVICE_NAME_MAX_LEN size is 8!
27 #endif
28
29 static DfmSessionData_t* pxDfmSessionData = (void*)0;
30
31 DfmResult_t prvGetSessionStorageVersion(DfmSessionStorage_t* pxSessionStorage, uint32_t* pulVersion);
32 DfmResult_t prvGetSessionStorageEnabled(DfmSessionStorage_t* pxSessionStorage, uint32_t* pulEnabled);
33
xDfmSessionInitialize(DfmSessionData_t * pxBuffer)34 DfmResult_t xDfmSessionInitialize(DfmSessionData_t* pxBuffer)
35 {
36 uint32_t i;
37 uint32_t ulBytesWritten;
38
39 if (pxBuffer == (void*)0)
40 {
41 return DFM_FAIL;
42 }
43
44 pxDfmSessionData = pxBuffer;
45
46 pxDfmSessionData->ulAlertCounter = 0;
47
48 pxDfmSessionData->ulProduct = DFM_CFG_PRODUCTID;
49
50 pxDfmSessionData->xStorageStrategy = DFM_CFG_STORAGE_STRATEGY;
51 pxDfmSessionData->xCloudStrategy = DFM_CFG_CLOUD_STRATEGY;
52 pxDfmSessionData->xSessionIdStrategy = DFM_CFG_SESSIONID_STRATEGY;
53
54 pxDfmSessionData->ulDfmStatus = DFM_STATUS_CODE_OK;
55
56 /* We disable it here */
57 pxDfmSessionData->ulEnabled = DFM_DISABLED;
58
59 if (pxDfmSessionData->xSessionIdStrategy == DFM_SESSIONID_STRATEGY_ONSTARTUP)
60 {
61 /* Verify that the user supplied callback has been set */
62 if (xDfmUserGetUniqueSessionID == 0)
63 {
64 return DFM_FAIL;
65 }
66
67 if (xDfmUserGetUniqueSessionID(pxDfmSessionData->cUniqueSessionIdBuffer, DFM_SESSION_ID_MAX_LEN, &ulBytesWritten) == DFM_FAIL) /*cstat !MISRAC2012-Rule-14.3_b The User implementation used for MISRA always returns DFM_SUCCESS so this check will never be true. In a real system that will not be the case.*/
68 {
69 return DFM_FAIL;
70 }
71
72 if (pxDfmSessionData->cUniqueSessionIdBuffer[0] == (char)0)
73 {
74 return DFM_FAIL;
75 }
76 }
77 else
78 {
79 pxDfmSessionData->cUniqueSessionIdBuffer[0] = (char)0;
80 }
81
82 pxDfmSessionData->cDeviceNameBuffer[0] = (char)0;
83
84 for (i = 0; i < (uint32_t)DFM_CFG_FIRMWARE_VERSION_MAX_LEN; i++)
85 {
86 pxDfmSessionData->cFirmwareVersionBuffer[i] = (char)(DFM_CFG_FIRMWARE_VERSION)[i];
87
88 if (pxDfmSessionData->cFirmwareVersionBuffer[i] == (char)0)
89 {
90 break;
91 }
92 }
93
94 pxDfmSessionData->ulInitialized = 1;
95
96 return DFM_SUCCESS;
97 }
98
xDfmSessionEnable(uint32_t ulOverride)99 DfmResult_t xDfmSessionEnable(uint32_t ulOverride)
100 {
101 uint8_t cSessionStorageBuffer[8] = {0}; /* This must be large enough to hold all previous versions of DfmSessionStorage_t */
102 uint32_t ulStoredEnabledValue = DFM_SESSION_STORAGE_DUMMY_VALUE;
103
104 if (pxDfmSessionData == (void*)0)
105 {
106 return DFM_FAIL;
107 }
108
109 if (pxDfmSessionData->ulInitialized == 0UL)
110 {
111 return DFM_FAIL;
112 }
113
114 if (ulDfmIsInitialized() == 0UL)
115 {
116 return DFM_FAIL;
117 }
118
119 /* Already enabled? */
120 if (pxDfmSessionData->ulEnabled == DFM_ENABLED)
121 {
122 return DFM_SUCCESS;
123 }
124
125 /* Is a previous session stored? */
126 if (xDfmStorageGetSession(cSessionStorageBuffer, sizeof(cSessionStorageBuffer)) == DFM_SUCCESS)
127 {
128 if (prvGetSessionStorageEnabled((DfmSessionStorage_t*)cSessionStorageBuffer, &ulStoredEnabledValue) == DFM_FAIL) /*cstat !MISRAC2012-Rule-11.3 We use an untyped buffer to retrieve the session data since we can't know what version and size it might have been stored in the past. The stored Session data might be larger than the current DfmSessionStorage_t*/
129 {
130 /* Unexpected error */
131 ulStoredEnabledValue = DFM_SESSION_STORAGE_DUMMY_VALUE;
132 }
133 }
134
135 if ((ulStoredEnabledValue == DFM_SESSION_STORAGE_DUMMY_VALUE) || ((ulOverride == 1UL) && (ulStoredEnabledValue == DFM_DISABLED)))
136 {
137 /* Couldn't read stored value or we override a disabled value */
138 ((DfmSessionStorage_t*)cSessionStorageBuffer)->ulVersion = DFM_SESSION_STORAGE_VERSION; /*cstat !MISRAC2012-Rule-11.3 We use an untyped buffer to retrieve the session data since we can't know what version and size it might have been stored in the past. The stored Session data might be larger than the current DfmSessionStorage_t*/
139 ((DfmSessionStorage_t*)cSessionStorageBuffer)->ulEnabled = DFM_ENABLED; /*cstat !MISRAC2012-Rule-11.3 We use an untyped buffer to retrieve the session data since we can't know what version and size it might have been stored in the past. The stored Session data might be larger than the current DfmSessionStorage_t*/
140
141 (void)xDfmStorageStoreSession(cSessionStorageBuffer, sizeof(DfmSessionStorage_t)); /* Attempt to store the session info. We can't really do anything if it fails. */
142
143 ulStoredEnabledValue = DFM_ENABLED;
144 }
145
146 if (ulStoredEnabledValue == DFM_DISABLED)
147 {
148 /* We are expressly disabled and not overriding */
149 return DFM_FAIL;
150 }
151
152 pxDfmSessionData->ulEnabled = DFM_ENABLED;
153
154 return DFM_SUCCESS;
155 }
156
xDfmSessionDisable(uint32_t ulRemember)157 DfmResult_t xDfmSessionDisable(uint32_t ulRemember)
158 {
159 uint8_t cSessionStorageBuffer[8] = { 0 }; /* This must be large enough to hold all previous versions of DfmSessionStorage_t */
160 uint32_t ulStoredEnabledValue = DFM_SESSION_STORAGE_DUMMY_VALUE;
161
162 if (pxDfmSessionData == (void*)0)
163 {
164 return DFM_FAIL;
165 }
166
167 if (pxDfmSessionData->ulInitialized == 0UL)
168 {
169 return DFM_FAIL;
170 }
171
172 /* Is a previous session stored? */
173 if (xDfmStorageGetSession(cSessionStorageBuffer, sizeof(cSessionStorageBuffer)) == DFM_SUCCESS)
174 {
175 if (prvGetSessionStorageEnabled((DfmSessionStorage_t*)cSessionStorageBuffer, &ulStoredEnabledValue) == DFM_FAIL) /*cstat !MISRAC2012-Rule-11.3 We use an untyped buffer to retrieve the session data since we can't know what version and size it might have been stored in the past. The stored Session data might be larger than the current DfmSessionStorage_t*/
176 {
177 /* Unexpected error */
178 ulStoredEnabledValue = DFM_SESSION_STORAGE_DUMMY_VALUE;
179 }
180 }
181
182 if (ulStoredEnabledValue != DFM_DISABLED)
183 {
184 /* We didn't find disabled */
185 ((DfmSessionStorage_t*)cSessionStorageBuffer)->ulVersion = DFM_SESSION_STORAGE_VERSION; /*cstat !MISRAC2012-Rule-11.3 We use an untyped buffer to retrieve the session data since we can't know what version and size it might have been stored in the past. The stored Session data might be larger than the current DfmSessionStorage_t*/
186 ((DfmSessionStorage_t*)cSessionStorageBuffer)->ulEnabled = DFM_DISABLED; /*cstat !MISRAC2012-Rule-11.3 We use an untyped buffer to retrieve the session data since we can't know what version and size it might have been stored in the past. The stored Session data might be larger than the current DfmSessionStorage_t*/
187
188 if (ulRemember != 0UL)
189 {
190 (void)xDfmStorageStoreSession(cSessionStorageBuffer, sizeof(DfmSessionStorage_t)); /* Attempt to store the session info. We can't really do anything if it fails. */
191 }
192 }
193
194 pxDfmSessionData->ulEnabled = DFM_DISABLED;
195
196 return DFM_SUCCESS;
197 }
198
ulDfmSessionIsEnabled()199 uint32_t ulDfmSessionIsEnabled()
200 {
201 if (pxDfmSessionData == (void*)0)
202 {
203 return 0;
204 }
205
206 if (pxDfmSessionData->ulInitialized == 0UL)
207 {
208 return 0;
209 }
210
211 if (ulDfmIsInitialized() == 0UL)
212 {
213 return 0;
214 }
215
216 return (uint32_t)(pxDfmSessionData->ulEnabled == DFM_ENABLED);
217 }
218
xDfmSessionGetUniqueSessionId(char ** pszUniqueSessionId)219 DfmResult_t xDfmSessionGetUniqueSessionId(char **pszUniqueSessionId)
220 {
221 uint32_t ulBytesWritten = 0UL;
222
223 if (pxDfmSessionData == (void*)0)
224 {
225 return DFM_FAIL;
226 }
227
228 if (pxDfmSessionData->ulInitialized == 0UL)
229 {
230 return DFM_FAIL;
231 }
232
233 if (pszUniqueSessionId == (void*)0)
234 {
235 return DFM_FAIL;
236 }
237
238 if (pxDfmSessionData->cUniqueSessionIdBuffer[0] == (char)0)
239 {
240 if (pxDfmSessionData->xSessionIdStrategy == DFM_SESSIONID_STRATEGY_ONALERT)
241 {
242 /* Verify that the user supplied callback has been set */
243 if (xDfmUserGetUniqueSessionID == 0)
244 {
245 return DFM_FAIL;
246 }
247
248 /* Attempt to get a valid session id. Reserve last buffer slot for null termination. */
249 if (xDfmUserGetUniqueSessionID(pxDfmSessionData->cUniqueSessionIdBuffer, (uint32_t)(DFM_SESSION_ID_MAX_LEN) - 1UL, &ulBytesWritten) == DFM_FAIL) /*cstat !MISRAC2012-Rule-14.3_b The User implementation used for MISRA always returns DFM_SUCCESS so this check will never be true. In a real system that will not be the case.*/
250 {
251 return DFM_FAIL;
252 }
253
254 if (pxDfmSessionData->cUniqueSessionIdBuffer[0] == (char)0)
255 {
256 return DFM_FAIL;
257 }
258
259 if (ulBytesWritten > (uint32_t)(DFM_SESSION_ID_MAX_LEN) - 1UL)
260 {
261 /* Wrote outside buffer? */
262 return DFM_FAIL;
263 }
264
265 /* Make sure we have null termination */
266 pxDfmSessionData->cUniqueSessionIdBuffer[ulBytesWritten] = (char)0;
267 }
268 else
269 {
270 /* This should have been set on startup! */
271 return DFM_FAIL;
272 }
273 }
274
275 *pszUniqueSessionId = pxDfmSessionData->cUniqueSessionIdBuffer;
276
277 return DFM_SUCCESS;
278 }
279
xDfmSessionSetDeviceName(const char * szDeviceName)280 DfmResult_t xDfmSessionSetDeviceName(const char* szDeviceName)
281 {
282 if (pxDfmSessionData == (void*)0)
283 {
284 return DFM_FAIL;
285 }
286
287 if (pxDfmSessionData->ulInitialized == 0UL)
288 {
289 return DFM_FAIL;
290 }
291
292 if (szDeviceName == (void*)0)
293 {
294 return DFM_FAIL;
295 }
296
297 /* Copy the device name string, but make sure we leave the last byte for zero termination */
298 for (int i = 0; i < DFM_DEVICE_NAME_MAX_LEN - 1; i++)
299 {
300 pxDfmSessionData->cDeviceNameBuffer[i] = szDeviceName[i];
301
302 /* Break at zero termination */
303 if (szDeviceName[i] == (char)0)
304 {
305 break;
306 }
307 }
308
309 pxDfmSessionData->cDeviceNameBuffer[DFM_DEVICE_NAME_MAX_LEN - 1] = (char)0;
310
311 return DFM_SUCCESS;
312 }
313
xDfmSessionGetDeviceName(const char ** pszDeviceName)314 DfmResult_t xDfmSessionGetDeviceName(const char** pszDeviceName)
315 {
316 uint32_t ulBytesWritten = 0UL;
317
318 if (pxDfmSessionData == (void*)0)
319 {
320 return DFM_FAIL;
321 }
322
323 if (pxDfmSessionData->ulInitialized == 0UL)
324 {
325 return DFM_FAIL;
326 }
327
328 if (pszDeviceName == (void*)0)
329 {
330 return DFM_FAIL;
331 }
332
333 if (pxDfmSessionData->cDeviceNameBuffer[0] == (char)0)
334 {
335 /* Verify that the user supplied callback has been set */
336 if (xDfmUserGetDeviceName == 0)
337 {
338 return DFM_FAIL;
339 }
340
341 /* Attempt to get a valid device name. Reserve last buffer slot for null termination. */
342 if (xDfmUserGetDeviceName(pxDfmSessionData->cDeviceNameBuffer, (uint32_t)(DFM_DEVICE_NAME_MAX_LEN) - 1UL, &ulBytesWritten) == DFM_FAIL) /*cstat !MISRAC2012-Rule-14.3_b The User implementation used for MISRA always returns DFM_SUCCESS so this check will never be true. In a real system that will not be the case.*/
343 {
344 return DFM_FAIL;
345 }
346
347 if (pxDfmSessionData->cDeviceNameBuffer[0] == (char)0)
348 {
349 return DFM_FAIL;
350 }
351
352 if (ulBytesWritten > (uint32_t)(DFM_DEVICE_NAME_MAX_LEN) - 1UL)
353 {
354 /* Wrote too much, no room for null termination! */
355 return DFM_FAIL;
356 }
357
358 /* Make sure we have null termination */
359 pxDfmSessionData->cDeviceNameBuffer[ulBytesWritten] = (char)0;
360 }
361
362 *pszDeviceName = pxDfmSessionData->cDeviceNameBuffer;
363
364 return DFM_SUCCESS;
365 }
366
xDfmSessionGenerateNewAlertId(void)367 DfmResult_t xDfmSessionGenerateNewAlertId(void)
368 {
369 if (pxDfmSessionData == (void*)0)
370 {
371 return DFM_FAIL;
372 }
373
374 if (pxDfmSessionData->ulInitialized == 0UL)
375 {
376 return DFM_FAIL;
377 }
378
379 /* alertIDs start at 1 */
380 pxDfmSessionData->ulAlertCounter++;
381
382 return DFM_SUCCESS;
383 }
384
xDfmSessionGetAlertId(uint32_t * pulAlertId)385 DfmResult_t xDfmSessionGetAlertId(uint32_t* pulAlertId)
386 {
387 if (pxDfmSessionData == (void*)0)
388 {
389 return DFM_FAIL;
390 }
391
392 if (pxDfmSessionData->ulInitialized == 0UL)
393 {
394 return DFM_FAIL;
395 }
396
397 if (pulAlertId == (void*)0)
398 {
399 return DFM_FAIL;
400 }
401
402 *pulAlertId = pxDfmSessionData->ulAlertCounter;
403
404 return DFM_SUCCESS;
405 }
406
xDfmSessionGetProduct(uint32_t * pulProduct)407 DfmResult_t xDfmSessionGetProduct(uint32_t* pulProduct)
408 {
409 if (pxDfmSessionData == (void*)0)
410 {
411 return DFM_FAIL;
412 }
413
414 if (pxDfmSessionData->ulInitialized == 0UL)
415 {
416 return DFM_FAIL;
417 }
418
419 if (pulProduct == (void*)0)
420 {
421 return DFM_FAIL;
422 }
423
424 *pulProduct = pxDfmSessionData->ulProduct;
425
426 return DFM_SUCCESS;
427 }
428
xDfmSessionGetFirmwareVersion(char ** pszFirmwareVersion)429 DfmResult_t xDfmSessionGetFirmwareVersion(char** pszFirmwareVersion)
430 {
431 if (pxDfmSessionData == (void*)0)
432 {
433 return DFM_FAIL;
434 }
435
436 if (pxDfmSessionData->ulInitialized == 0UL)
437 {
438 return DFM_FAIL;
439 }
440
441 if (pszFirmwareVersion == (void*)0)
442 {
443 return DFM_FAIL;
444 }
445
446 *pszFirmwareVersion = pxDfmSessionData->cFirmwareVersionBuffer;
447 return DFM_SUCCESS;
448 }
449
xDfmSessionSetStatus(uint32_t ulStatus)450 DfmResult_t xDfmSessionSetStatus(uint32_t ulStatus)
451 {
452 if (pxDfmSessionData == (void*)0)
453 {
454 return DFM_FAIL;
455 }
456
457 if (pxDfmSessionData->ulInitialized == 0UL)
458 {
459 return DFM_FAIL;
460 }
461
462 if (pxDfmSessionData->ulDfmStatus != DFM_STATUS_CODE_OK)
463 {
464 return DFM_FAIL;
465 }
466
467 pxDfmSessionData->ulDfmStatus = ulStatus;
468
469 return DFM_SUCCESS;
470 }
471
xDfmSessionGetStatus(uint32_t * pulStatus)472 DfmResult_t xDfmSessionGetStatus(uint32_t* pulStatus)
473 {
474 if (pxDfmSessionData == (void*)0)
475 {
476 return DFM_FAIL;
477 }
478
479 if (pxDfmSessionData->ulInitialized == 0UL)
480 {
481 return DFM_FAIL;
482 }
483
484 if (pulStatus == (void*)0)
485 {
486 return DFM_FAIL;
487 }
488
489 *pulStatus = pxDfmSessionData->ulDfmStatus;
490
491 return DFM_SUCCESS;
492 }
493
xDfmSessionSetCloudStrategy(DfmCloudStrategy_t xStrategy)494 DfmResult_t xDfmSessionSetCloudStrategy(DfmCloudStrategy_t xStrategy)
495 {
496 if (pxDfmSessionData == (void*)0)
497 {
498 return DFM_FAIL;
499 }
500
501 if (pxDfmSessionData->ulInitialized == 0UL)
502 {
503 return DFM_FAIL;
504 }
505
506 pxDfmSessionData->xCloudStrategy = xStrategy;
507
508 return DFM_SUCCESS;
509 }
510
xDfmSessionGetCloudStrategy(DfmCloudStrategy_t * pxStrategy)511 DfmResult_t xDfmSessionGetCloudStrategy(DfmCloudStrategy_t* pxStrategy)
512 {
513 if (pxDfmSessionData == (void*)0)
514 {
515 return DFM_FAIL;
516 }
517
518 if (pxDfmSessionData->ulInitialized == 0UL)
519 {
520 return DFM_FAIL;
521 }
522
523 if (pxStrategy == (void*)0)
524 {
525 return DFM_FAIL;
526 }
527
528 *pxStrategy = pxDfmSessionData->xCloudStrategy;
529
530 return DFM_SUCCESS;
531 }
532
xDfmSessionSetStorageStrategy(DfmStorageStrategy_t xStrategy)533 DfmResult_t xDfmSessionSetStorageStrategy(DfmStorageStrategy_t xStrategy)
534 {
535 if (pxDfmSessionData == (void*)0)
536 {
537 return DFM_FAIL;
538 }
539
540 if (pxDfmSessionData->ulInitialized == 0UL)
541 {
542 return DFM_FAIL;
543 }
544
545 pxDfmSessionData->xStorageStrategy = xStrategy;
546
547 return DFM_SUCCESS;
548 }
549
xDfmSessionGetStorageStrategy(DfmStorageStrategy_t * pxStrategy)550 DfmResult_t xDfmSessionGetStorageStrategy(DfmStorageStrategy_t* pxStrategy)
551 {
552 if (pxDfmSessionData == (void*)0)
553 {
554 return DFM_FAIL;
555 }
556
557 if (pxDfmSessionData->ulInitialized == 0UL)
558 {
559 return DFM_FAIL;
560 }
561
562 if (pxStrategy == (void*)0)
563 {
564 return DFM_FAIL;
565 }
566
567 *pxStrategy = pxDfmSessionData->xStorageStrategy;
568
569 return DFM_SUCCESS;
570 }
571
xDfmSessionSetSessionIdStrategy(DfmSessionIdStrategy_t xStrategy)572 DfmResult_t xDfmSessionSetSessionIdStrategy(DfmSessionIdStrategy_t xStrategy)
573 {
574 if (pxDfmSessionData == (void*)0)
575 {
576 return DFM_FAIL;
577 }
578
579 if (pxDfmSessionData->ulInitialized == 0UL)
580 {
581 return DFM_FAIL;
582 }
583
584 pxDfmSessionData->xSessionIdStrategy = xStrategy;
585
586 return DFM_SUCCESS;
587 }
588
xDfmSessionGetSessionIdStrategy(DfmSessionIdStrategy_t * pxStrategy)589 DfmResult_t xDfmSessionGetSessionIdStrategy(DfmSessionIdStrategy_t* pxStrategy)
590 {
591 if (pxDfmSessionData == (void*)0)
592 {
593 return DFM_FAIL;
594 }
595
596 if (pxDfmSessionData->ulInitialized == 0UL)
597 {
598 return DFM_FAIL;
599 }
600
601 if (pxStrategy == (void*)0)
602 {
603 return DFM_FAIL;
604 }
605
606 *pxStrategy = pxDfmSessionData->xSessionIdStrategy;
607
608 return DFM_SUCCESS;
609 }
610
prvGetSessionStorageVersion(DfmSessionStorage_t * pxSessionStorage,uint32_t * pulVersion)611 DfmResult_t prvGetSessionStorageVersion(DfmSessionStorage_t* pxSessionStorage, uint32_t* pulVersion)
612 {
613 if (pxSessionStorage->ulVersion != 1UL)
614 {
615 return DFM_FAIL;
616 }
617
618 *pulVersion = pxSessionStorage->ulVersion;
619
620 return DFM_SUCCESS;
621 }
622
prvGetSessionStorageEnabled(DfmSessionStorage_t * pxSessionStorage,uint32_t * pulEnabled)623 DfmResult_t prvGetSessionStorageEnabled(DfmSessionStorage_t* pxSessionStorage, uint32_t* pulEnabled)
624 {
625 if (pxSessionStorage->ulVersion != 1UL)
626 {
627 return DFM_FAIL;
628 }
629
630 *pulEnabled = pxSessionStorage->ulEnabled;
631
632 return DFM_SUCCESS;
633 }
634
635 #endif
636