1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
17 //-----------------------------------------------------------------------------
23 #include "util.h" // param_get32ex
25 #include "cmddata.h" // for g_debugmode
26 #include "commonutil.h" // Uint4bytetomemle
29 int32_t g_GraphBuffer
[MAX_GRAPH_TRACE_LEN
];
30 int32_t g_OperationBuffer
[MAX_GRAPH_TRACE_LEN
];
31 int32_t g_OverlayBuffer
[MAX_GRAPH_TRACE_LEN
];
32 bool g_useOverlays
= false;
33 size_t g_GraphTraceLen
;
34 buffer_savestate_t g_saveState_gb
;
35 marker_t g_MarkerA
, g_MarkerB
, g_MarkerC
, g_MarkerD
;
36 marker_t
*g_TempMarkers
;
37 uint8_t g_TempMarkerSize
= 0;
39 /* write a manchester bit to the graph
41 void AppendGraph(bool redraw
, uint16_t clock
, int bit
) {
42 uint16_t half
= clock
/ 2;
46 // overflow/underflow safe checks ... Assumptions:
47 // _Assert(g_GraphTraceLen >= 0);
48 // _Assert(g_GraphTraceLen <= MAX_GRAPH_TRACE_LEN);
49 // If this occurs, allow partial rendering, up to the last sample...
50 if ((MAX_GRAPH_TRACE_LEN
- g_GraphTraceLen
) < half
) {
51 PrintAndLogEx(DEBUG
, "WARNING: AppendGraph() - Request exceeds max graph length");
52 end
= MAX_GRAPH_TRACE_LEN
- g_GraphTraceLen
;
55 if ((MAX_GRAPH_TRACE_LEN
- g_GraphTraceLen
) < end
) {
56 PrintAndLogEx(DEBUG
, "WARNING: AppendGraph() - Request exceeds max graph length");
57 end
= MAX_GRAPH_TRACE_LEN
- g_GraphTraceLen
;
60 //set first half the clock bit (all 1's or 0's for a 0 or 1 bit)
61 for (i
= 0; i
< half
; ++i
) {
62 g_GraphBuffer
[g_GraphTraceLen
++] = bit
;
65 //set second half of the clock bit (all 0's or 1's for a 0 or 1 bit)
66 for (; i
< end
; ++i
) {
67 g_GraphBuffer
[g_GraphTraceLen
++] = bit
^ 1;
75 // clear out our graph window and all the buffers associated with it
76 size_t ClearGraph(bool redraw
) {
77 size_t gtl
= g_GraphTraceLen
;
79 memset(g_GraphBuffer
, 0x00, g_GraphTraceLen
);
80 memset(g_OperationBuffer
, 0x00, g_GraphTraceLen
);
81 memset(g_OverlayBuffer
, 0x00, g_GraphTraceLen
);
87 g_useOverlays
= false;
89 remove_temporary_markers();
102 void setGraphBuffer(const uint8_t *src
, size_t size
) {
109 if (size
> MAX_GRAPH_TRACE_LEN
) {
110 size
= MAX_GRAPH_TRACE_LEN
;
113 for (size_t i
= 0; i
< size
; ++i
) {
114 g_GraphBuffer
[i
] = src
[i
] - 128;
115 g_OperationBuffer
[i
] = src
[i
] - 128;
118 remove_temporary_markers();
119 g_GraphTraceLen
= size
;
120 RepaintGraphWindow();
123 // This function assumes that the length of dest array >= g_GraphTraceLen.
124 // If the length of dest array is less than g_GraphTraceLen, use getFromGraphBufferEx(dest, maxLen) instead.
125 size_t getFromGraphBuffer(uint8_t *dest
) {
126 return getFromGraphBufferEx(dest
, g_GraphTraceLen
);
129 size_t getFromGraphBufferEx(uint8_t *dest
, size_t maxLen
) {
134 if (g_GraphTraceLen
== 0) {
139 maxLen
= (maxLen
< g_GraphTraceLen
) ? maxLen
: g_GraphTraceLen
;
140 for (i
= 0; i
< maxLen
; ++i
) {
142 if (g_GraphBuffer
[i
] > 127) {
143 g_GraphBuffer
[i
] = 127;
146 if (g_GraphBuffer
[i
] < -127) {
147 g_GraphBuffer
[i
] = -127;
149 dest
[i
] = (uint8_t)(g_GraphBuffer
[i
] + 128);
154 //TODO: In progress function to get chunks of data from the GB w/o modifying the GB
155 //Currently seems like it doesn't work correctly?
156 size_t getGraphBufferChunk(uint8_t *dest
, size_t start
, size_t end
) {
161 if (g_GraphTraceLen
== 0) {
170 end
= (end
< g_GraphTraceLen
) ? end
: g_GraphTraceLen
;
171 for (i
= 0; i
< (end
- start
); i
++) {
172 value
= g_GraphBuffer
[start
+ i
];
174 //Trim the data to fit into an uint8_t
177 } else if (value
< -127) {
181 dest
[i
] = ((uint8_t)(value
+ 128));
187 // A simple test to see if there is any data inside the Graph Buffer.
188 bool HasGraphData(void) {
189 if (g_GraphTraceLen
== 0) {
190 PrintAndLogEx(NORMAL
, "No data available, try reading something first");
197 bool isGraphBitstream(void) {
198 // convert to bitstream if necessary
199 for (int i
= 0; i
< g_GraphTraceLen
; i
++) {
200 if (g_GraphBuffer
[i
] > 1 || g_GraphBuffer
[i
] < 0) {
207 void convertGraphFromBitstream(void) {
208 convertGraphFromBitstreamEx(1, 0);
211 void convertGraphFromBitstreamEx(int hi
, int low
) {
212 for (int i
= 0; i
< g_GraphTraceLen
; i
++) {
214 if (g_GraphBuffer
[i
] == hi
)
215 g_GraphBuffer
[i
] = 127;
216 else if (g_GraphBuffer
[i
] == low
)
217 g_GraphBuffer
[i
] = -127;
219 g_GraphBuffer
[i
] = 0;
222 uint8_t *bits
= calloc(g_GraphTraceLen
, sizeof(uint8_t));
224 PrintAndLogEx(DEBUG
, "ERR: convertGraphFromBitstreamEx, failed to allocate memory");
228 size_t size
= getFromGraphBuffer(bits
);
230 PrintAndLogEx(WARNING
, "Failed to copy from graphbuffer");
235 // set signal properties low/high/mean/amplitude and is_noise detection
236 computeSignalProperties(bits
, size
);
238 RepaintGraphWindow();
241 // Get or auto-detect ask clock rate
242 int GetAskClock(const char *str
, bool verbose
) {
243 if (getSignalProperties()->isnoise
) {
247 int clock1
= param_get32ex(str
, 0, 0, 10);
254 uint8_t *bits
= calloc(MAX_GRAPH_TRACE_LEN
, sizeof(uint8_t));
256 PrintAndLogEx(WARNING
, "Failed to allocate memory");
260 size_t size
= getFromGraphBuffer(bits
);
262 PrintAndLogEx(WARNING
, "Failed to copy from graphbuffer");
267 size_t ststart
= 0, stend
= 0;
268 bool st
= DetectST(bits
, &size
, &clock1
, &ststart
, &stend
);
271 idx
= DetectASKClock(bits
, size
, &clock1
, 20);
275 setClockGrid(clock1
, idx
);
277 // Only print this message if we're not looping something
278 if (verbose
|| g_debugMode
) {
279 PrintAndLogEx(SUCCESS
, "Auto-detected clock rate: %d, Best Starting Position: %d", clock1
, idx
);
286 int GetPskCarrier(bool verbose
) {
287 if (getSignalProperties()->isnoise
) {
291 uint8_t *bits
= calloc(MAX_GRAPH_TRACE_LEN
, sizeof(uint8_t));
293 PrintAndLogEx(WARNING
, "Failed to allocate memory");
297 size_t size
= getFromGraphBuffer(bits
);
299 PrintAndLogEx(WARNING
, "Failed to copy from graphbuffer");
304 uint16_t fc
= countFC(bits
, size
, false);
307 uint8_t carrier
= fc
& 0xFF;
308 if (carrier
!= 2 && carrier
!= 4 && carrier
!= 8) {
312 if ((fc
>> 8) == 10 && carrier
== 8) {
315 // Only print this message if we're not looping something
317 PrintAndLogEx(SUCCESS
, "Auto-detected PSK carrier rate: %d", carrier
);
323 int GetPskClock(const char *str
, bool verbose
) {
325 if (getSignalProperties()->isnoise
) {
329 int clock1
= param_get32ex(str
, 0, 0, 10);
335 uint8_t *bits
= calloc(MAX_GRAPH_TRACE_LEN
, sizeof(uint8_t));
337 PrintAndLogEx(WARNING
, "Failed to allocate memory");
341 size_t size
= getFromGraphBuffer(bits
);
343 PrintAndLogEx(WARNING
, "Failed to copy from graphbuffer");
348 size_t firstPhaseShiftLoc
= 0;
349 uint8_t curPhase
= 0, fc
= 0;
350 clock1
= DetectPSKClock(bits
, size
, 0, &firstPhaseShiftLoc
, &curPhase
, &fc
);
353 setClockGrid(clock1
, firstPhaseShiftLoc
);
356 // Only print this message if we're not looping something
358 PrintAndLogEx(SUCCESS
, "Auto-detected clock rate: %d", clock1
);
365 int GetNrzClock(const char *str
, bool verbose
) {
367 if (getSignalProperties()->isnoise
) {
371 int clock1
= param_get32ex(str
, 0, 0, 10);
377 uint8_t *bits
= calloc(MAX_GRAPH_TRACE_LEN
, sizeof(uint8_t));
379 PrintAndLogEx(WARNING
, "Failed to allocate memory");
383 size_t size
= getFromGraphBuffer(bits
);
385 PrintAndLogEx(WARNING
, "Failed to copy from graphbuffer");
390 size_t clkStartIdx
= 0;
391 clock1
= DetectNRZClock(bits
, size
, 0, &clkStartIdx
);
392 setClockGrid(clock1
, clkStartIdx
);
393 // Only print this message if we're not looping something
395 PrintAndLogEx(SUCCESS
, "Auto-detected clock rate: %d", clock1
);
403 //attempt to detect the field clock and bit clock for FSK
404 int GetFskClock(const char *str
, bool verbose
) {
406 int clock1
= param_get32ex(str
, 0, 0, 10);
411 uint8_t fc1
= 0, fc2
= 0, rf1
= 0;
412 int firstClockEdge
= 0;
414 if (fskClocks(&fc1
, &fc2
, &rf1
, &firstClockEdge
) == false) {
418 if ((fc1
== 10 && fc2
== 8) || (fc1
== 8 && fc2
== 5)) {
420 PrintAndLogEx(SUCCESS
, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1
, fc2
, rf1
);
423 setClockGrid(rf1
, firstClockEdge
);
427 PrintAndLogEx(DEBUG
, "DEBUG: unknown fsk field clock detected");
428 PrintAndLogEx(DEBUG
, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1
, fc2
, rf1
);
432 bool fskClocks(uint8_t *fc1
, uint8_t *fc2
, uint8_t *rf1
, int *firstClockEdge
) {
434 if (getSignalProperties()->isnoise
) {
438 uint8_t *bits
= calloc(MAX_GRAPH_TRACE_LEN
, sizeof(uint8_t));
440 PrintAndLogEx(WARNING
, "Failed to allocate memory");
444 size_t size
= getFromGraphBuffer(bits
);
446 PrintAndLogEx(WARNING
, "Failed to copy from graphbuffer");
451 uint16_t ans
= countFC(bits
, size
, true);
453 PrintAndLogEx(DEBUG
, "DEBUG: No data found");
458 *fc1
= (ans
>> 8) & 0xFF;
460 *rf1
= detectFSKClk(bits
, size
, *fc1
, *fc2
, firstClockEdge
);
465 PrintAndLogEx(DEBUG
, "DEBUG: Clock detect error");
471 void add_temporary_marker(uint32_t position
, const char *label
) {
472 if (g_TempMarkerSize
== 0) { //Initialize the marker array
473 g_TempMarkers
= (marker_t
*)calloc(1, sizeof(marker_t
));
474 } else { //add more space to the marker array using realloc()
475 marker_t
*temp
= (marker_t
*)realloc(g_TempMarkers
, ((g_TempMarkerSize
+ 1) * sizeof(marker_t
)));
477 if (temp
== NULL
) { //Unable to reallocate memory for a new marker
478 PrintAndLogEx(FAILED
, "Unable to allocate memory for a new temporary marker!");
482 //Set g_TempMarkers to the new pointer
483 g_TempMarkers
= temp
;
487 g_TempMarkers
[g_TempMarkerSize
].pos
= position
;
489 char *markerLabel
= (char *)calloc(1, strlen(label
) + 1);
490 strcpy(markerLabel
, label
);
492 if (strlen(markerLabel
) > 30) {
493 PrintAndLogEx(WARNING
, "Label for temporary marker too long! Trunicating...");
494 markerLabel
[30] = '\0';
497 strncpy(g_TempMarkers
[g_TempMarkerSize
].label
, markerLabel
, 30);
500 memset(markerLabel
, 0x00, strlen(label
));
504 void remove_temporary_markers(void) {
505 if (g_TempMarkerSize
== 0) return;
507 memset(g_TempMarkers
, 0x00, (g_TempMarkerSize
* sizeof(marker_t
)));
509 g_TempMarkerSize
= 0;
512 buffer_savestate_t
save_buffer32(uint32_t *src
, size_t length
) {
513 //calloc the memory needed
514 uint32_t *savedBuffer
= (uint32_t *)calloc(length
, sizeof(uint32_t));
516 //Make a copy of the source buffer
517 memcpy(savedBuffer
, src
, (length
* sizeof(uint32_t)));
519 buffer_savestate_t bst
= {
520 .type
= sizeof(uint32_t),
521 .bufferSize
= length
,
522 .buffer
= savedBuffer
,
529 buffer_savestate_t
save_bufferS32(int32_t *src
, size_t length
) {
530 //calloc the memory needed
531 uint32_t *savedBuffer
= (uint32_t *)calloc(length
, (sizeof(uint32_t)));
533 //Make a copy of the source buffer
534 memcpy(savedBuffer
, src
, (length
* sizeof(uint32_t)));
536 buffer_savestate_t bst
= {
537 .type
= (sizeof(int32_t) >> 8),
538 .bufferSize
= length
,
539 .buffer
= savedBuffer
,
546 buffer_savestate_t
save_buffer8(uint8_t *src
, size_t length
) {
547 // We are going to be packing the 8-bit source buffer into
548 // the 32-bit backing buffer, so the input length is going to be
549 // 1/4 of the size needed
550 size_t buffSize
= (length
/ 4);
552 PrintAndLogEx(DEBUG
, "(save_buffer8) buffSize = %llu, length = %llu", buffSize
, length
);
556 PrintAndLogEx(DEBUG
, "(save_buffer8) new buffSize = %llu", buffSize
);
559 // calloc the memory needed
560 uint32_t *savedBuffer
= (uint32_t *)calloc(buffSize
, sizeof(uint32_t));
563 // Pack the source array into the backing array
564 for (size_t i
= 0; i
< length
; i
+= 4) {
565 savedBuffer
[index
] = MemLeToUint4byte(src
+ i
);
569 buffer_savestate_t bst
= {
570 .type
= sizeof(uint8_t),
571 .bufferSize
= buffSize
,
572 .buffer
= savedBuffer
,
573 .padding
= ((buffSize
* 4) - length
)
579 size_t restore_buffer32(buffer_savestate_t saveState
, uint32_t *dest
) {
580 if (saveState
.type
!= sizeof(uint32_t)) {
581 PrintAndLogEx(WARNING
, "Invalid Save State type! Expected uint32_t!");
582 PrintAndLogEx(WARNING
, "Buffer not modified!\n");
586 memcpy(dest
, saveState
.buffer
, (saveState
.bufferSize
* sizeof(uint32_t)));
588 return saveState
.bufferSize
;
591 size_t restore_bufferS32(buffer_savestate_t saveState
, int32_t *dest
) {
592 if (saveState
.type
!= (sizeof(int32_t) >> 8)) {
593 PrintAndLogEx(WARNING
, "Invalid Save State type! Expected int32_t");
594 PrintAndLogEx(WARNING
, "Buffer not modified!\n");
598 memcpy(dest
, saveState
.buffer
, (saveState
.bufferSize
* sizeof(int32_t)));
600 return saveState
.bufferSize
;
603 size_t restore_buffer8(buffer_savestate_t saveState
, uint8_t *dest
) {
604 if (saveState
.type
!= sizeof(uint8_t)) {
605 PrintAndLogEx(WARNING
, "Invalid Save State type! Expected uint8_t!");
606 PrintAndLogEx(WARNING
, "Buffer not modified!\n");
611 size_t length
= ((saveState
.bufferSize
* 4) - saveState
.padding
);
614 for (size_t i
= 0; i
< saveState
.bufferSize
; i
++) {
615 dest
[index
++] = saveState
.buffer
[i
];
616 if (index
== length
) break;
617 dest
[index
++] = (saveState
.buffer
[i
] >> 8) & 0xFF;
618 if (index
== length
) break;
619 dest
[index
++] = (saveState
.buffer
[i
] >> 16) & 0xFF;
620 if (index
== length
) break;
621 dest
[index
++] = (saveState
.buffer
[i
] >> 24) & 0xFF;
622 if (index
== length
) break;