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